blob: 57e420a318dac53154aa2d026d97e5f7433d8ca8 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05302 * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070066#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070068#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053077#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080080#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080081
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053082#ifdef DYNAMIC_LOG_ENABLED
83#include <log_xml_parser.h>
84#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
85#include <log_utils.h>
86#endif
87
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053089/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
90#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070092#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053093#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070095#define PROXY_OPEN_RETRY_COUNT 100
96#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080097
Mingming Yin08c7e312015-03-16 18:10:58 -070098#ifdef USE_LL_AS_PRIMARY_OUTPUT
99#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
100#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
101#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800102#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700103#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
104#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800105
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700106#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700107#define DEFAULT_VOIP_BUF_DURATION_MS 20
108#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
109#define DEFAULT_VOIP_SAMP_RATE 48000
110
111#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
112
113struct pcm_config default_pcm_config_voip_copp = {
114 .channels = 1,
115 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
116 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
117 .period_count = 2,
118 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800119 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
120 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700121};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700122
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700123#define MIN_CHANNEL_COUNT 1
124#define DEFAULT_CHANNEL_COUNT 2
125#define MAX_HIFI_CHANNEL_COUNT 8
126
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700127static unsigned int configured_low_latency_capture_period_size =
128 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
129
Haynes Mathew George16081042017-05-31 17:16:49 -0700130#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
131#define MMAP_PERIOD_COUNT_MIN 32
132#define MMAP_PERIOD_COUNT_MAX 512
133#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
134
Eric Laurentb23d5282013-05-14 15:27:20 -0700135struct pcm_config pcm_config_deep_buffer = {
136 .channels = 2,
137 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
138 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
139 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
140 .format = PCM_FORMAT_S16_LE,
141 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
142 .stop_threshold = INT_MAX,
143 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
144};
145
146struct pcm_config pcm_config_low_latency = {
147 .channels = 2,
148 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
149 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
150 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
151 .format = PCM_FORMAT_S16_LE,
152 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
153 .stop_threshold = INT_MAX,
154 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
155};
156
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700157static int af_period_multiplier = 4;
158struct pcm_config pcm_config_rt = {
159 .channels = 2,
160 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
161 .period_size = ULL_PERIOD_SIZE, //1 ms
162 .period_count = 512, //=> buffer size is 512ms
163 .format = PCM_FORMAT_S16_LE,
164 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
165 .stop_threshold = INT_MAX,
166 .silence_threshold = 0,
167 .silence_size = 0,
168 .avail_min = ULL_PERIOD_SIZE, //1 ms
169};
170
Eric Laurentb23d5282013-05-14 15:27:20 -0700171struct pcm_config pcm_config_hdmi_multi = {
172 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
173 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
174 .period_size = HDMI_MULTI_PERIOD_SIZE,
175 .period_count = HDMI_MULTI_PERIOD_COUNT,
176 .format = PCM_FORMAT_S16_LE,
177 .start_threshold = 0,
178 .stop_threshold = INT_MAX,
179 .avail_min = 0,
180};
181
Haynes Mathew George16081042017-05-31 17:16:49 -0700182struct pcm_config pcm_config_mmap_playback = {
183 .channels = 2,
184 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
185 .period_size = MMAP_PERIOD_SIZE,
186 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
187 .format = PCM_FORMAT_S16_LE,
188 .start_threshold = MMAP_PERIOD_SIZE*8,
189 .stop_threshold = INT32_MAX,
190 .silence_threshold = 0,
191 .silence_size = 0,
192 .avail_min = MMAP_PERIOD_SIZE, //1 ms
193};
194
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700195struct pcm_config pcm_config_hifi = {
196 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
197 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
198 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
199 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
200 .format = PCM_FORMAT_S24_3LE,
201 .start_threshold = 0,
202 .stop_threshold = INT_MAX,
203 .avail_min = 0,
204};
205
Eric Laurentb23d5282013-05-14 15:27:20 -0700206struct pcm_config pcm_config_audio_capture = {
207 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700208 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
209 .format = PCM_FORMAT_S16_LE,
210};
211
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700212struct pcm_config pcm_config_audio_capture_rt = {
213 .channels = 2,
214 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
215 .period_size = ULL_PERIOD_SIZE,
216 .period_count = 512,
217 .format = PCM_FORMAT_S16_LE,
218 .start_threshold = 0,
219 .stop_threshold = INT_MAX,
220 .silence_threshold = 0,
221 .silence_size = 0,
222 .avail_min = ULL_PERIOD_SIZE, //1 ms
223};
224
Haynes Mathew George16081042017-05-31 17:16:49 -0700225struct pcm_config pcm_config_mmap_capture = {
226 .channels = 2,
227 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
228 .period_size = MMAP_PERIOD_SIZE,
229 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
230 .format = PCM_FORMAT_S16_LE,
231 .start_threshold = 0,
232 .stop_threshold = INT_MAX,
233 .silence_threshold = 0,
234 .silence_size = 0,
235 .avail_min = MMAP_PERIOD_SIZE, //1 ms
236};
237
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700238#define AFE_PROXY_CHANNEL_COUNT 2
239#define AFE_PROXY_SAMPLING_RATE 48000
240
241#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
242#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
243
244struct pcm_config pcm_config_afe_proxy_playback = {
245 .channels = AFE_PROXY_CHANNEL_COUNT,
246 .rate = AFE_PROXY_SAMPLING_RATE,
247 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
248 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
249 .format = PCM_FORMAT_S16_LE,
250 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
251 .stop_threshold = INT_MAX,
252 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
253};
254
255#define AFE_PROXY_RECORD_PERIOD_SIZE 768
256#define AFE_PROXY_RECORD_PERIOD_COUNT 4
257
258struct pcm_config pcm_config_afe_proxy_record = {
259 .channels = AFE_PROXY_CHANNEL_COUNT,
260 .rate = AFE_PROXY_SAMPLING_RATE,
261 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
262 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
263 .format = PCM_FORMAT_S16_LE,
264 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
265 .stop_threshold = INT_MAX,
266 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
267};
268
Ashish Jainf1eaa582016-05-23 20:54:24 +0530269#define AUDIO_MAX_PCM_FORMATS 7
270
271const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
272 [AUDIO_FORMAT_DEFAULT] = 0,
273 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
274 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
275 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
276 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
277 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
278 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
279};
280
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800281const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700282 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
283 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700284 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
285 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700286 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700287 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700288 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
289 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
290 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
291 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
292 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
293 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
294 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
295 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700296 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
297 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700298 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700299
Eric Laurentb23d5282013-05-14 15:27:20 -0700300 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700301 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530302 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
303 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
304 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530305 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
306 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700307 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700308 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700309 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700310 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700311
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800312 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800313 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700314 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700315
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700316 [USECASE_VOICE2_CALL] = "voice2-call",
317 [USECASE_VOLTE_CALL] = "volte-call",
318 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800319 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800320 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
321 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800322 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700323 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
324 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
325 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800326 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
327 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
328 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
329
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700330 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
331 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700332 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
333 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700334
335 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
336 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530337 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700338
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530339 /* Transcode loopback cases */
340 [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700341
342 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
343 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530344 /* For Interactive Audio Streams */
345 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
346 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
347 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
348 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
349 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
350 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
351 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
352 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700353
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800354 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
355
356 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback"
Eric Laurentb23d5282013-05-14 15:27:20 -0700357};
358
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700359static const audio_usecase_t offload_usecases[] = {
360 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700361 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
362 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
363 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
364 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
365 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
366 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
367 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
368 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700369};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800370
Varun Balaraje49253e2017-07-06 19:48:56 +0530371static const audio_usecase_t interactive_usecases[] = {
372 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
373 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
374 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
375 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
376 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
377 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
378 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
379 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
380};
381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800382#define STRING_TO_ENUM(string) { #string, string }
383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800384struct string_to_enum {
385 const char *name;
386 uint32_t value;
387};
388
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700389static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800390 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800391 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
392 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
393 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700394 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800395 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
396 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800397 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700398 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
399 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
400 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
401 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
402 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
403 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
404 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
405 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
406 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
407 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
408 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800409};
410
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700411static const struct string_to_enum formats_name_to_enum_table[] = {
412 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
413 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
414 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700415 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
416 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
417 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700418 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800419 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
420 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700421 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800422};
423
424//list of all supported sample rates by HDMI specification.
425static const int out_hdmi_sample_rates[] = {
426 32000, 44100, 48000, 88200, 96000, 176400, 192000,
427};
428
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700429static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800430 STRING_TO_ENUM(32000),
431 STRING_TO_ENUM(44100),
432 STRING_TO_ENUM(48000),
433 STRING_TO_ENUM(88200),
434 STRING_TO_ENUM(96000),
435 STRING_TO_ENUM(176400),
436 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700437};
438
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700439static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700440static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700441static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700442//cache last MBDRC cal step level
443static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700444
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530445static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
446static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800447static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530448
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700449static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
450 int flags __unused)
451{
452 int dir = 0;
453 switch (uc_id) {
454 case USECASE_AUDIO_RECORD_LOW_LATENCY:
455 dir = 1;
456 case USECASE_AUDIO_PLAYBACK_ULL:
457 break;
458 default:
459 return false;
460 }
461
462 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
463 PCM_PLAYBACK : PCM_CAPTURE);
464 if (adev->adm_is_noirq_avail)
465 return adev->adm_is_noirq_avail(adev->adm_data,
466 adev->snd_card, dev_id, dir);
467 return false;
468}
469
470static void register_out_stream(struct stream_out *out)
471{
472 struct audio_device *adev = out->dev;
473 if (is_offload_usecase(out->usecase) ||
474 !adev->adm_register_output_stream)
475 return;
476
477 // register stream first for backward compatibility
478 adev->adm_register_output_stream(adev->adm_data,
479 out->handle,
480 out->flags);
481
482 if (!adev->adm_set_config)
483 return;
484
485 if (out->realtime)
486 adev->adm_set_config(adev->adm_data,
487 out->handle,
488 out->pcm, &out->config);
489}
490
491static void register_in_stream(struct stream_in *in)
492{
493 struct audio_device *adev = in->dev;
494 if (!adev->adm_register_input_stream)
495 return;
496
497 adev->adm_register_input_stream(adev->adm_data,
498 in->capture_handle,
499 in->flags);
500
501 if (!adev->adm_set_config)
502 return;
503
504 if (in->realtime)
505 adev->adm_set_config(adev->adm_data,
506 in->capture_handle,
507 in->pcm,
508 &in->config);
509}
510
511static void request_out_focus(struct stream_out *out, long ns)
512{
513 struct audio_device *adev = out->dev;
514
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700515 if (adev->adm_request_focus_v2)
516 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
517 else if (adev->adm_request_focus)
518 adev->adm_request_focus(adev->adm_data, out->handle);
519}
520
521static void request_in_focus(struct stream_in *in, long ns)
522{
523 struct audio_device *adev = in->dev;
524
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700525 if (adev->adm_request_focus_v2)
526 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
527 else if (adev->adm_request_focus)
528 adev->adm_request_focus(adev->adm_data, in->capture_handle);
529}
530
531static void release_out_focus(struct stream_out *out)
532{
533 struct audio_device *adev = out->dev;
534
535 if (adev->adm_abandon_focus)
536 adev->adm_abandon_focus(adev->adm_data, out->handle);
537}
538
539static void release_in_focus(struct stream_in *in)
540{
541 struct audio_device *adev = in->dev;
542 if (adev->adm_abandon_focus)
543 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
544}
545
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530546static int parse_snd_card_status(struct str_parms *parms, int *card,
547 card_status_t *status)
548{
549 char value[32]={0};
550 char state[32]={0};
551
552 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
553 if (ret < 0)
554 return -1;
555
556 // sscanf should be okay as value is of max length 32.
557 // same as sizeof state.
558 if (sscanf(value, "%d,%s", card, state) < 2)
559 return -1;
560
561 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
562 CARD_STATUS_OFFLINE;
563 return 0;
564}
565
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700566static inline void adjust_frames_for_device_delay(struct stream_out *out,
567 uint32_t *dsp_frames) {
568 // Adjustment accounts for A2dp encoder latency with offload usecases
569 // Note: Encoder latency is returned in ms.
570 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
571 unsigned long offset =
572 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
573 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
574 }
575}
576
vivek mehtaa76401a2015-04-24 14:12:15 -0700577__attribute__ ((visibility ("default")))
578bool audio_hw_send_gain_dep_calibration(int level) {
579 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700580 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700581
582 pthread_mutex_lock(&adev_init_lock);
583
584 if (adev != NULL && adev->platform != NULL) {
585 pthread_mutex_lock(&adev->lock);
586 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700587
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530588 // cache level info for any of the use case which
589 // was not started.
590 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700591
vivek mehtaa76401a2015-04-24 14:12:15 -0700592 pthread_mutex_unlock(&adev->lock);
593 } else {
594 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
595 }
596
597 pthread_mutex_unlock(&adev_init_lock);
598
599 return ret_val;
600}
601
Ashish Jain5106d362016-05-11 19:23:33 +0530602static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
603{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800604 bool gapless_enabled = false;
605 const char *mixer_ctl_name = "Compress Gapless Playback";
606 struct mixer_ctl *ctl;
607
608 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700609 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530610
611 /*Disable gapless if its AV playback*/
612 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800613
614 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
615 if (!ctl) {
616 ALOGE("%s: Could not get ctl for mixer cmd - %s",
617 __func__, mixer_ctl_name);
618 return -EINVAL;
619 }
620
621 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
622 ALOGE("%s: Could not set gapless mode %d",
623 __func__, gapless_enabled);
624 return -EINVAL;
625 }
626 return 0;
627}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700628
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700629__attribute__ ((visibility ("default")))
630int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
631 int table_size) {
632 int ret_val = 0;
633 ALOGV("%s: enter ... ", __func__);
634
635 pthread_mutex_lock(&adev_init_lock);
636 if (adev == NULL) {
637 ALOGW("%s: adev is NULL .... ", __func__);
638 goto done;
639 }
640
641 pthread_mutex_lock(&adev->lock);
642 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
643 pthread_mutex_unlock(&adev->lock);
644done:
645 pthread_mutex_unlock(&adev_init_lock);
646 ALOGV("%s: exit ... ", __func__);
647 return ret_val;
648}
649
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700650static bool is_supported_format(audio_format_t format)
651{
Eric Laurent86e17132013-09-12 17:49:30 -0700652 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530653 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530654 format == AUDIO_FORMAT_AAC_LC ||
655 format == AUDIO_FORMAT_AAC_HE_V1 ||
656 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530657 format == AUDIO_FORMAT_AAC_ADTS_LC ||
658 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
659 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530660 format == AUDIO_FORMAT_AAC_LATM_LC ||
661 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
662 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530663 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
664 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530665 format == AUDIO_FORMAT_PCM_FLOAT ||
666 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700667 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530668 format == AUDIO_FORMAT_AC3 ||
669 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700670 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530671 format == AUDIO_FORMAT_DTS ||
672 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800673 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530674 format == AUDIO_FORMAT_ALAC ||
675 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530676 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530677 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800678 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530679 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700680 format == AUDIO_FORMAT_APTX ||
681 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800682 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700683
684 return false;
685}
686
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700687static inline bool is_mmap_usecase(audio_usecase_t uc_id)
688{
689 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
690 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
691}
692
Avinash Vaish71a8b972014-07-24 15:36:33 +0530693static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
694 struct audio_usecase *uc_info)
695{
696 struct listnode *node;
697 struct audio_usecase *usecase;
698
699 if (uc_info == NULL)
700 return -EINVAL;
701
702 /* Re-route all voice usecases on the shared backend other than the
703 specified usecase to new snd devices */
704 list_for_each(node, &adev->usecase_list) {
705 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800706 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530707 enable_audio_route(adev, usecase);
708 }
709 return 0;
710}
711
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530712static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530713{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530714 ALOGV("%s", __func__);
715 audio_route_apply_and_update_path(adev->audio_route,
716 "asrc-mode");
717 adev->asrc_mode_enabled = true;
718}
719
720static void disable_asrc_mode(struct audio_device *adev)
721{
722 ALOGV("%s", __func__);
723 audio_route_reset_and_update_path(adev->audio_route,
724 "asrc-mode");
725 adev->asrc_mode_enabled = false;
726}
727
728/*
729 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
730 * 44.1 or Native DSD backends are enabled for any of current use case.
731 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
732 * - Disable current mix path use case(Headphone backend) and re-enable it with
733 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
734 * e.g. Naitve DSD or Headphone 44.1 -> + 48
735 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530736static void check_and_set_asrc_mode(struct audio_device *adev,
737 struct audio_usecase *uc_info,
738 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530739{
740 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530741 int i, num_new_devices = 0;
742 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
743 /*
744 *Split snd device for new combo use case
745 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
746 */
747 if (platform_split_snd_device(adev->platform,
748 snd_device,
749 &num_new_devices,
750 split_new_snd_devices) == 0) {
751 for (i = 0; i < num_new_devices; i++)
752 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
753 } else {
754 int new_backend_idx = platform_get_backend_index(snd_device);
755 if (((new_backend_idx == HEADPHONE_BACKEND) ||
756 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
757 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
758 !adev->asrc_mode_enabled) {
759 struct listnode *node = NULL;
760 struct audio_usecase *uc = NULL;
761 struct stream_out *curr_out = NULL;
762 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
763 int i, num_devices, ret = 0;
764 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530765
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530766 list_for_each(node, &adev->usecase_list) {
767 uc = node_to_item(node, struct audio_usecase, list);
768 curr_out = (struct stream_out*) uc->stream.out;
769 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
770 /*
771 *Split snd device for existing combo use case
772 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
773 */
774 ret = platform_split_snd_device(adev->platform,
775 uc->out_snd_device,
776 &num_devices,
777 split_snd_devices);
778 if (ret < 0 || num_devices == 0) {
779 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
780 split_snd_devices[0] = uc->out_snd_device;
781 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800782 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530783 for (i = 0; i < num_devices; i++) {
784 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
785 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
786 if((new_backend_idx == HEADPHONE_BACKEND) &&
787 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
788 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
789 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
790 __func__);
791 enable_asrc_mode(adev);
792 break;
793 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
794 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
795 (usecase_backend_idx == HEADPHONE_BACKEND)) {
796 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
797 __func__);
798 disable_audio_route(adev, uc);
799 disable_snd_device(adev, uc->out_snd_device);
800 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
801 if (new_backend_idx == DSD_NATIVE_BACKEND)
802 audio_route_apply_and_update_path(adev->audio_route,
803 "hph-true-highquality-mode");
804 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
805 (curr_out->bit_width >= 24))
806 audio_route_apply_and_update_path(adev->audio_route,
807 "hph-highquality-mode");
808 enable_asrc_mode(adev);
809 enable_snd_device(adev, uc->out_snd_device);
810 enable_audio_route(adev, uc);
811 break;
812 }
813 }
814 // reset split devices count
815 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800816 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530817 if (adev->asrc_mode_enabled)
818 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530819 }
820 }
821 }
822}
823
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700824#ifdef DYNAMIC_ECNS_ENABLED
825static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
826 struct audio_effect_config effect_config,
827 unsigned int param_value)
828{
829 char mixer_ctl_name[] = "Audio Effect";
830 struct mixer_ctl *ctl;
831 long set_values[6];
832 struct stream_in *in = adev->active_input;
833
834 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
835 if (!ctl) {
836 ALOGE("%s: Could not get mixer ctl - %s",
837 __func__, mixer_ctl_name);
838 return -EINVAL;
839 }
840
841 set_values[0] = 1; //0:Rx 1:Tx
842 set_values[1] = in->app_type_cfg.app_type;
843 set_values[2] = (long)effect_config.module_id;
844 set_values[3] = (long)effect_config.instance_id;
845 set_values[4] = (long)effect_config.param_id;
846 set_values[5] = param_value;
847
848 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
849
850 return 0;
851
852}
853
854static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
855 int effect_type, unsigned int *param_value)
856{
857 int ret = 0;
858 struct audio_effect_config other_effect_config;
859 struct audio_usecase *usecase = NULL;
860 struct stream_in *in = adev->active_input;
861
862 usecase = get_usecase_from_list(adev, in->usecase);
863 if (!usecase)
864 return -EINVAL;
865
866 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
867 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
868 if (ret < 0) {
869 ALOGE("%s Failed to get effect params %d", __func__, ret);
870 return ret;
871 }
872
873 if (module_id == other_effect_config.module_id) {
874 //Same module id for AEC/NS. Values need to be combined
875 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
876 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
877 *param_value |= other_effect_config.param_value;
878 }
879 }
880
881 return ret;
882}
883
884static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
885{
886 struct audio_effect_config effect_config;
887 struct audio_usecase *usecase = NULL;
888 int ret = 0;
889 unsigned int param_value = 0;
890 struct stream_in *in = adev->active_input;
891
892 if (!in) {
893 ALOGE("%s: Invalid input stream", __func__);
894 return -EINVAL;
895 }
896
897 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
898
899 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800900 if (usecase == NULL) {
901 ALOGE("%s: Could not find the usecase (%d) in the list",
902 __func__, in->usecase);
903 return -EINVAL;
904 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700905
906 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
907 if (ret < 0) {
908 ALOGE("%s Failed to get module id %d", __func__, ret);
909 return ret;
910 }
911 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
912 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
913
914 if(enable)
915 param_value = effect_config.param_value;
916
917 /*Special handling for AEC & NS effects Param values need to be
918 updated if module ids are same*/
919
920 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
921 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
922 if (ret < 0)
923 return ret;
924 }
925
926 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
927
928 return ret;
929}
930
931static void check_and_enable_effect(struct audio_device *adev)
932{
933
934 if (adev->active_input->enable_aec) {
935 enable_disable_effect(adev, EFFECT_AEC, true);
936 }
937
938 if (adev->active_input->enable_ns &&
939 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
940 enable_disable_effect(adev, EFFECT_NS, true);
941 }
942}
943#else
944#define enable_disable_effect(x, y, z) ENOSYS
945#define check_and_enable_effect(x) ENOSYS
946#endif
947
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700948int pcm_ioctl(struct pcm *pcm, int request, ...)
949{
950 va_list ap;
951 void * arg;
952 int pcm_fd = *(int*)pcm;
953
954 va_start(ap, request);
955 arg = va_arg(ap, void *);
956 va_end(ap);
957
958 return ioctl(pcm_fd, request, arg);
959}
960
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700961int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700962 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800963{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700964 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700965 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530966 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800967
968 if (usecase == NULL)
969 return -EINVAL;
970
971 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
972
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800973 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700974 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800975 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700976 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800977
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800978#ifdef DS1_DOLBY_DAP_ENABLED
979 audio_extn_dolby_set_dmid(adev);
980 audio_extn_dolby_set_endpoint(adev);
981#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700982 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700983 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530984 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700985 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530986 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530987 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
988 out = usecase->stream.out;
989 if (out && out->compr)
990 audio_extn_utils_compress_set_clk_rec_mode(usecase);
991 }
992
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800993 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700994 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700995 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700996 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800997 ALOGV("%s: exit", __func__);
998 return 0;
999}
1000
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001001int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001002 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001003{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001004 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001005 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001006
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301007 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001008 return -EINVAL;
1009
1010 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001011 if (usecase->type == PCM_CAPTURE)
1012 snd_device = usecase->in_snd_device;
1013 else
1014 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001015 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001016 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001017 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001018 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001019 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301020 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021 ALOGV("%s: exit", __func__);
1022 return 0;
1023}
1024
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001025int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001026 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001027{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301028 int i, num_devices = 0;
1029 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001030 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1031
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001032 if (snd_device < SND_DEVICE_MIN ||
1033 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001034 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001035 return -EINVAL;
1036 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001037
1038 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001039
1040 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
1041 ALOGE("%s: Invalid sound device returned", __func__);
1042 return -EINVAL;
1043 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001044 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -07001045 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001046 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001047 return 0;
1048 }
1049
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301050
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001051 if (audio_extn_spkr_prot_is_enabled())
1052 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001053
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001054 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1055 audio_extn_spkr_prot_is_enabled()) {
1056 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001057 adev->snd_dev_ref_cnt[snd_device]--;
1058 return -EINVAL;
1059 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001060 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001061 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001062 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001063 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001064 return -EINVAL;
1065 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001066 } else if (platform_split_snd_device(adev->platform,
1067 snd_device,
1068 &num_devices,
1069 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301070 for (i = 0; i < num_devices; i++) {
1071 enable_snd_device(adev, new_snd_devices[i]);
1072 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001073 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001074 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301075
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301076
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301077 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1078 (audio_extn_a2dp_start_playback() < 0)) {
1079 ALOGE(" fail to configure A2dp control path ");
1080 return -EINVAL;
1081 }
1082
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001083 /* due to the possibility of calibration overwrite between listen
1084 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001085 audio_extn_sound_trigger_update_device_status(snd_device,
1086 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301087 audio_extn_listen_update_device_status(snd_device,
1088 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001089 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001090 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001091 audio_extn_sound_trigger_update_device_status(snd_device,
1092 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301093 audio_extn_listen_update_device_status(snd_device,
1094 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001095 return -EINVAL;
1096 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001097 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001098 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301099
1100 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1101 !adev->native_playback_enabled &&
1102 audio_is_true_native_stream_active(adev)) {
1103 ALOGD("%s: %d: napb: enabling native mode in hardware",
1104 __func__, __LINE__);
1105 audio_route_apply_and_update_path(adev->audio_route,
1106 "true-native-mode");
1107 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301108 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001109 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1110 (audio_extn_ffv_get_stream() == adev->active_input)) {
1111 ALOGD("%s: init ec ref loopback", __func__);
1112 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1113 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001114 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001115 return 0;
1116}
1117
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001118int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001119 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001120{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301121 int i, num_devices = 0;
1122 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001123 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1124
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001125 if (snd_device < SND_DEVICE_MIN ||
1126 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001127 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001128 return -EINVAL;
1129 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001130 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1131 ALOGE("%s: device ref cnt is already 0", __func__);
1132 return -EINVAL;
1133 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001134
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001136
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001137 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1138 ALOGE("%s: Invalid sound device returned", __func__);
1139 return -EINVAL;
1140 }
1141
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001142 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001143 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301144
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001145 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1146 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001147 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001148
1149 // when speaker device is disabled, reset swap.
1150 // will be renabled on usecase start
1151 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001152 } else if (platform_split_snd_device(adev->platform,
1153 snd_device,
1154 &num_devices,
1155 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301156 for (i = 0; i < num_devices; i++) {
1157 disable_snd_device(adev, new_snd_devices[i]);
1158 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001159 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001160 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001161 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001162
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301163 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1164 audio_extn_a2dp_stop_playback();
1165
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001166 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301167 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301168 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1169 adev->native_playback_enabled) {
1170 ALOGD("%s: %d: napb: disabling native mode in hardware",
1171 __func__, __LINE__);
1172 audio_route_reset_and_update_path(adev->audio_route,
1173 "true-native-mode");
1174 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301175 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1176 adev->asrc_mode_enabled) {
1177 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301178 disable_asrc_mode(adev);
1179 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301180 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001181 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1182 (audio_extn_ffv_get_stream() == adev->active_input)) {
1183 ALOGD("%s: deinit ec ref loopback", __func__);
1184 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1185 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001186 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001187 audio_extn_sound_trigger_update_device_status(snd_device,
1188 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301189 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001190 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001191 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001193 return 0;
1194}
1195
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001196/*
1197 legend:
1198 uc - existing usecase
1199 new_uc - new usecase
1200 d1, d11, d2 - SND_DEVICE enums
1201 a1, a2 - corresponding ANDROID device enums
1202 B1, B2 - backend strings
1203
1204case 1
1205 uc->dev d1 (a1) B1
1206 new_uc->dev d1 (a1), d2 (a2) B1, B2
1207
1208 resolution: disable and enable uc->dev on d1
1209
1210case 2
1211 uc->dev d1 (a1) B1
1212 new_uc->dev d11 (a1) B1
1213
1214 resolution: need to switch uc since d1 and d11 are related
1215 (e.g. speaker and voice-speaker)
1216 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1217
1218case 3
1219 uc->dev d1 (a1) B1
1220 new_uc->dev d2 (a2) B2
1221
1222 resolution: no need to switch uc
1223
1224case 4
1225 uc->dev d1 (a1) B1
1226 new_uc->dev d2 (a2) B1
1227
1228 resolution: disable enable uc-dev on d2 since backends match
1229 we cannot enable two streams on two different devices if they
1230 share the same backend. e.g. if offload is on speaker device using
1231 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1232 using the same backend, offload must also be switched to voice-handset.
1233
1234case 5
1235 uc->dev d1 (a1) B1
1236 new_uc->dev d1 (a1), d2 (a2) B1
1237
1238 resolution: disable enable uc-dev on d2 since backends match
1239 we cannot enable two streams on two different devices if they
1240 share the same backend.
1241
1242case 6
1243 uc->dev d1 (a1) B1
1244 new_uc->dev d2 (a1) B2
1245
1246 resolution: no need to switch
1247
1248case 7
1249 uc->dev d1 (a1), d2 (a2) B1, B2
1250 new_uc->dev d1 (a1) B1
1251
1252 resolution: no need to switch
1253
Zhou Song4ba65882018-07-09 14:48:07 +08001254case 8
1255 uc->dev d1 (a1) B1
1256 new_uc->dev d11 (a1), d2 (a2) B1, B2
1257 resolution: compared to case 1, for this case, d1 and d11 are related
1258 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001259*/
1260static snd_device_t derive_playback_snd_device(void * platform,
1261 struct audio_usecase *uc,
1262 struct audio_usecase *new_uc,
1263 snd_device_t new_snd_device)
1264{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301265 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001266
1267 snd_device_t d1 = uc->out_snd_device;
1268 snd_device_t d2 = new_snd_device;
1269
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301270 switch (uc->type) {
1271 case TRANSCODE_LOOPBACK :
1272 a1 = uc->stream.inout->out_config.devices;
1273 a2 = new_uc->stream.inout->out_config.devices;
1274 break;
1275 default :
1276 a1 = uc->stream.out->devices;
1277 a2 = new_uc->stream.out->devices;
1278 break;
1279 }
1280
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001281 // Treat as a special case when a1 and a2 are not disjoint
1282 if ((a1 != a2) && (a1 & a2)) {
1283 snd_device_t d3[2];
1284 int num_devices = 0;
1285 int ret = platform_split_snd_device(platform,
1286 popcount(a1) > 1 ? d1 : d2,
1287 &num_devices,
1288 d3);
1289 if (ret < 0) {
1290 if (ret != -ENOSYS) {
1291 ALOGW("%s failed to split snd_device %d",
1292 __func__,
1293 popcount(a1) > 1 ? d1 : d2);
1294 }
1295 goto end;
1296 }
1297
1298 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1299 // But if it does happen, we need to give priority to d2 if
1300 // the combo devices active on the existing usecase share a backend.
1301 // This is because we cannot have a usecase active on a combo device
1302 // and a new usecase requests one device in this combo pair.
1303 if (platform_check_backends_match(d3[0], d3[1])) {
1304 return d2; // case 5
1305 } else {
Zhou Song671be042018-08-27 15:33:52 +08001306 // check if d1 is related to any of d3's OR
1307 // old uc is combo device but new_uc is one of the combo device
1308 if (d1 == d3[0] || d1 == d3[1] || popcount(a1) > 1)
1309 return d1; // case 1, 7
Zhou Song4ba65882018-07-09 14:48:07 +08001310 else
1311 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001312 }
1313 } else {
1314 if (platform_check_backends_match(d1, d2)) {
1315 return d2; // case 2, 4
1316 } else {
1317 return d1; // case 6, 3
1318 }
1319 }
1320
1321end:
1322 return d2; // return whatever was calculated before.
1323}
1324
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001325static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301326 struct audio_usecase *uc_info,
1327 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001328{
1329 struct listnode *node;
1330 struct audio_usecase *usecase;
1331 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301332 snd_device_t uc_derive_snd_device;
1333 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001334 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1335 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001336 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301337 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001338 /*
1339 * This function is to make sure that all the usecases that are active on
1340 * the hardware codec backend are always routed to any one device that is
1341 * handled by the hardware codec.
1342 * For example, if low-latency and deep-buffer usecases are currently active
1343 * on speaker and out_set_parameters(headset) is received on low-latency
1344 * output, then we have to make sure deep-buffer is also switched to headset,
1345 * because of the limitation that both the devices cannot be enabled
1346 * at the same time as they share the same backend.
1347 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001348 /*
1349 * This call is to check if we need to force routing for a particular stream
1350 * If there is a backend configuration change for the device when a
1351 * new stream starts, then ADM needs to be closed and re-opened with the new
1352 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001353 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001354 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001355 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1356 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301357 /* For a2dp device reconfigure all active sessions
1358 * with new AFE encoder format based on a2dp state
1359 */
1360 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1361 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1362 audio_extn_a2dp_is_force_device_switch()) {
1363 force_routing = true;
1364 force_restart_session = true;
1365 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301366 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1367
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001368 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001369 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001370 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001371 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1372 switch_device[i] = false;
1373
1374 list_for_each(node, &adev->usecase_list) {
1375 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001376
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301377 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1378 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301379 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301380 platform_get_snd_device_name(usecase->out_snd_device),
1381 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301382 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1383 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1384 usecase, uc_info, snd_device);
1385 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1386 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1387 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1388 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001389 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301390 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1391 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1392 ((force_restart_session) ||
1393 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301394 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1395 __func__, use_case_table[usecase->id],
1396 platform_get_snd_device_name(usecase->out_snd_device));
1397 disable_audio_route(adev, usecase);
1398 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301399 /* Enable existing usecase on derived playback device */
1400 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301401 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301402 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001403 }
1404 }
1405
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301406 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1407 num_uc_to_switch);
1408
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001409 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001410 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001411
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301412 /* Make sure the previous devices to be disabled first and then enable the
1413 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001414 list_for_each(node, &adev->usecase_list) {
1415 usecase = node_to_item(node, struct audio_usecase, list);
1416 if (switch_device[usecase->id]) {
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001417 /* Check if sound device to be switched can be split and if any
1418 of the split devices match with derived sound device */
1419 platform_split_snd_device(adev->platform, usecase->out_snd_device,
1420 &num_devices, split_snd_devices);
1421 if (num_devices > 1) {
1422 for (i = 0; i < num_devices; i++) {
1423 /* Disable devices that do not match with derived sound device */
1424 if (split_snd_devices[i] != derive_snd_device[usecase->id]) {
1425 disable_snd_device(adev, split_snd_devices[i]);
1426 }
1427 }
1428 } else {
1429 disable_snd_device(adev, usecase->out_snd_device);
1430 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001431 }
1432 }
1433
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001434 list_for_each(node, &adev->usecase_list) {
1435 usecase = node_to_item(node, struct audio_usecase, list);
1436 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301437 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001438 }
1439 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001440
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001441 /* Re-route all the usecases on the shared backend other than the
1442 specified usecase to new snd devices */
1443 list_for_each(node, &adev->usecase_list) {
1444 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301445 /* Update the out_snd_device only before enabling the audio route */
1446 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301447 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301448 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301449 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301450 use_case_table[usecase->id],
1451 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001452 /* Update voc calibration before enabling VoIP route */
1453 if (usecase->type == VOIP_CALL)
1454 status = platform_switch_voice_call_device_post(adev->platform,
1455 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001456 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301457 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001458 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1459 out_set_voip_volume(&usecase->stream.out->stream,
1460 usecase->stream.out->volume_l,
1461 usecase->stream.out->volume_r);
1462 }
Yidong Huang7939a3b2018-01-23 17:32:30 +08001463 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1464 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1465 if (parms)
1466 audio_extn_fm_set_parameters(adev, parms);
1467 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301468 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001469 }
1470 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001471 }
1472}
1473
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301474static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001475 struct audio_usecase *uc_info,
1476 snd_device_t snd_device)
1477{
1478 struct listnode *node;
1479 struct audio_usecase *usecase;
1480 bool switch_device[AUDIO_USECASE_MAX];
1481 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301482 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001483 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001484
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301485 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1486 snd_device);
1487 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301488
1489 /*
1490 * Make sure out devices is checked against out codec backend device and
1491 * also in devices against in codec backend. Checking out device against in
1492 * codec backend or vice versa causes issues.
1493 */
1494 if (uc_info->type == PCM_CAPTURE)
1495 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001496 /*
1497 * This function is to make sure that all the active capture usecases
1498 * are always routed to the same input sound device.
1499 * For example, if audio-record and voice-call usecases are currently
1500 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1501 * is received for voice call then we have to make sure that audio-record
1502 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1503 * because of the limitation that two devices cannot be enabled
1504 * at the same time if they share the same backend.
1505 */
1506 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1507 switch_device[i] = false;
1508
1509 list_for_each(node, &adev->usecase_list) {
1510 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301511 /*
1512 * TODO: Enhance below condition to handle BT sco/USB multi recording
1513 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001514 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001515 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301516 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301517 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301518 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301519 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001520 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001521 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1522 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001523 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001524 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001525 switch_device[usecase->id] = true;
1526 num_uc_to_switch++;
1527 }
1528 }
1529
1530 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001531 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001532
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301533 /* Make sure the previous devices to be disabled first and then enable the
1534 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001535 list_for_each(node, &adev->usecase_list) {
1536 usecase = node_to_item(node, struct audio_usecase, list);
1537 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001538 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001539 }
1540 }
1541
1542 list_for_each(node, &adev->usecase_list) {
1543 usecase = node_to_item(node, struct audio_usecase, list);
1544 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001545 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001546 }
1547 }
1548
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001549 /* Re-route all the usecases on the shared backend other than the
1550 specified usecase to new snd devices */
1551 list_for_each(node, &adev->usecase_list) {
1552 usecase = node_to_item(node, struct audio_usecase, list);
1553 /* Update the in_snd_device only before enabling the audio route */
1554 if (switch_device[usecase->id] ) {
1555 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001556 if (usecase->type != VOICE_CALL) {
1557 /* Update voc calibration before enabling VoIP route */
1558 if (usecase->type == VOIP_CALL)
1559 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001560 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001561 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301562 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001563 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001564 }
1565 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001566 }
1567}
1568
Mingming Yin3a941d42016-02-17 18:08:05 -08001569static void reset_hdmi_sink_caps(struct stream_out *out) {
1570 int i = 0;
1571
1572 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1573 out->supported_channel_masks[i] = 0;
1574 }
1575 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1576 out->supported_formats[i] = 0;
1577 }
1578 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1579 out->supported_sample_rates[i] = 0;
1580 }
1581}
1582
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001584static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001585{
Mingming Yin3a941d42016-02-17 18:08:05 -08001586 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001587 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001588
Mingming Yin3a941d42016-02-17 18:08:05 -08001589 reset_hdmi_sink_caps(out);
1590
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001591 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001592 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001593 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001594 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001595 }
1596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001597 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001598 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001599 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001600 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001601 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1602 case 6:
1603 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1604 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1605 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1606 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1607 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1608 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001609 break;
1610 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001611 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001612 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001613 break;
1614 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001615
1616 // check channel format caps
1617 i = 0;
1618 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1619 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1620 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1621 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1622 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1623 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1624 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1625 }
1626
Ben Romberger1aaaf862017-04-06 17:49:46 -07001627 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1628 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1629 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1630 }
1631
Mingming Yin3a941d42016-02-17 18:08:05 -08001632 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1633 ALOGV(":%s HDMI supports DTS format", __func__);
1634 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1635 }
1636
1637 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1638 ALOGV(":%s HDMI supports DTS HD format", __func__);
1639 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1640 }
1641
Naresh Tanniru928f0862017-04-07 16:44:23 -07001642 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1643 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1644 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1645 }
1646
Mingming Yin3a941d42016-02-17 18:08:05 -08001647
1648 // check sample rate caps
1649 i = 0;
1650 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1651 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1652 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1653 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1654 }
1655 }
1656
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001657 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658}
1659
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001660static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1661 uint32_t *supported_sample_rates __unused,
1662 uint32_t max_rates __unused)
1663{
1664 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1665 supported_sample_rates,
1666 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301667 ssize_t i = 0;
1668
1669 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001670 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1671 supported_sample_rates[i]);
1672 }
1673 return count;
1674}
1675
1676static inline int read_usb_sup_channel_masks(bool is_playback,
1677 audio_channel_mask_t *supported_channel_masks,
1678 uint32_t max_masks)
1679{
1680 int channels = audio_extn_usb_get_max_channels(is_playback);
1681 int channel_count;
1682 uint32_t num_masks = 0;
1683 if (channels > MAX_HIFI_CHANNEL_COUNT)
1684 channels = MAX_HIFI_CHANNEL_COUNT;
1685
1686 if (is_playback) {
1687 // For playback we never report mono because the framework always outputs stereo
1688 channel_count = DEFAULT_CHANNEL_COUNT;
1689 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1690 // above 2 but we want indexed masks here. So we
1691 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1692 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1693 }
1694 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1695 supported_channel_masks[num_masks++] =
1696 audio_channel_mask_for_index_assignment_from_count(channel_count);
1697 }
1698 } else {
1699 // For capture we report all supported channel masks from 1 channel up.
1700 channel_count = MIN_CHANNEL_COUNT;
1701 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1702 // indexed mask
1703 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1704 supported_channel_masks[num_masks++] =
1705 audio_channel_in_mask_from_count(channel_count);
1706 }
1707 }
1708 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1709 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1710 return num_masks;
1711}
1712
1713static inline int read_usb_sup_formats(bool is_playback __unused,
1714 audio_format_t *supported_formats,
1715 uint32_t max_formats __unused)
1716{
1717 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1718 switch (bitwidth) {
1719 case 24:
1720 // XXX : usb.c returns 24 for s24 and s24_le?
1721 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1722 break;
1723 case 32:
1724 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1725 break;
1726 case 16:
1727 default :
1728 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1729 break;
1730 }
1731 ALOGV("%s: %s supported format %d", __func__,
1732 is_playback ? "P" : "C", bitwidth);
1733 return 1;
1734}
1735
1736static inline int read_usb_sup_params_and_compare(bool is_playback,
1737 audio_format_t *format,
1738 audio_format_t *supported_formats,
1739 uint32_t max_formats,
1740 audio_channel_mask_t *mask,
1741 audio_channel_mask_t *supported_channel_masks,
1742 uint32_t max_masks,
1743 uint32_t *rate,
1744 uint32_t *supported_sample_rates,
1745 uint32_t max_rates) {
1746 int ret = 0;
1747 int num_formats;
1748 int num_masks;
1749 int num_rates;
1750 int i;
1751
1752 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1753 max_formats);
1754 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1755 max_masks);
1756
1757 num_rates = read_usb_sup_sample_rates(is_playback,
1758 supported_sample_rates, max_rates);
1759
1760#define LUT(table, len, what, dflt) \
1761 for (i=0; i<len && (table[i] != what); i++); \
1762 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1763
1764 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1765 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1766 LUT(supported_sample_rates, num_rates, *rate, 0);
1767
1768#undef LUT
1769 return ret < 0 ? -EINVAL : 0; // HACK TBD
1770}
1771
Alexy Josephb1379942016-01-29 15:49:38 -08001772audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001773 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001774{
1775 struct audio_usecase *usecase;
1776 struct listnode *node;
1777
1778 list_for_each(node, &adev->usecase_list) {
1779 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001780 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001781 ALOGV("%s: usecase id %d", __func__, usecase->id);
1782 return usecase->id;
1783 }
1784 }
1785 return USECASE_INVALID;
1786}
1787
Alexy Josephb1379942016-01-29 15:49:38 -08001788struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001789 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001790{
1791 struct audio_usecase *usecase;
1792 struct listnode *node;
1793
1794 list_for_each(node, &adev->usecase_list) {
1795 usecase = node_to_item(node, struct audio_usecase, list);
1796 if (usecase->id == uc_id)
1797 return usecase;
1798 }
1799 return NULL;
1800}
1801
Dhananjay Kumard4833242016-10-06 22:09:12 +05301802struct stream_in *get_next_active_input(const struct audio_device *adev)
1803{
1804 struct audio_usecase *usecase;
1805 struct listnode *node;
1806
1807 list_for_each_reverse(node, &adev->usecase_list) {
1808 usecase = node_to_item(node, struct audio_usecase, list);
1809 if (usecase->type == PCM_CAPTURE)
1810 return usecase->stream.in;
1811 }
1812 return NULL;
1813}
1814
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301815/*
1816 * is a true native playback active
1817 */
1818bool audio_is_true_native_stream_active(struct audio_device *adev)
1819{
1820 bool active = false;
1821 int i = 0;
1822 struct listnode *node;
1823
1824 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1825 ALOGV("%s:napb: not in true mode or non hdphones device",
1826 __func__);
1827 active = false;
1828 goto exit;
1829 }
1830
1831 list_for_each(node, &adev->usecase_list) {
1832 struct audio_usecase *uc;
1833 uc = node_to_item(node, struct audio_usecase, list);
1834 struct stream_out *curr_out =
1835 (struct stream_out*) uc->stream.out;
1836
1837 if (curr_out && PCM_PLAYBACK == uc->type) {
1838 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1839 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1840 uc->id, curr_out->sample_rate,
1841 curr_out->bit_width,
1842 platform_get_snd_device_name(uc->out_snd_device));
1843
1844 if (is_offload_usecase(uc->id) &&
1845 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1846 active = true;
1847 ALOGD("%s:napb:native stream detected", __func__);
1848 }
1849 }
1850 }
1851exit:
1852 return active;
1853}
1854
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001855uint32_t adev_get_dsp_bit_width_enforce_mode()
1856{
1857 if (adev == NULL) {
1858 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1859 return 0;
1860 }
1861 return adev->dsp_bit_width_enforce_mode;
1862}
1863
1864static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1865{
1866 char value[PROPERTY_VALUE_MAX];
1867 int trial;
1868 uint32_t dsp_bit_width_enforce_mode = 0;
1869
1870 if (!mixer) {
1871 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1872 __func__);
1873 return 0;
1874 }
1875
1876 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1877 value, NULL) > 0) {
1878 trial = atoi(value);
1879 switch (trial) {
1880 case 16:
1881 dsp_bit_width_enforce_mode = 16;
1882 break;
1883 case 24:
1884 dsp_bit_width_enforce_mode = 24;
1885 break;
1886 case 32:
1887 dsp_bit_width_enforce_mode = 32;
1888 break;
1889 default:
1890 dsp_bit_width_enforce_mode = 0;
1891 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1892 break;
1893 }
1894 }
1895
1896 return dsp_bit_width_enforce_mode;
1897}
1898
1899static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1900 uint32_t enforce_mode,
1901 bool enable)
1902{
1903 struct mixer_ctl *ctl = NULL;
1904 const char *mixer_ctl_name = "ASM Bit Width";
1905 uint32_t asm_bit_width_mode = 0;
1906
1907 if (enforce_mode == 0) {
1908 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1909 return;
1910 }
1911
1912 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1913 if (!ctl) {
1914 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1915 __func__, mixer_ctl_name);
1916 return;
1917 }
1918
1919 if (enable)
1920 asm_bit_width_mode = enforce_mode;
1921 else
1922 asm_bit_width_mode = 0;
1923
1924 ALOGV("%s DSP bit width feature status is %d width=%d",
1925 __func__, enable, asm_bit_width_mode);
1926 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1927 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1928 asm_bit_width_mode);
1929
1930 return;
1931}
1932
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301933/*
1934 * if native DSD playback active
1935 */
1936bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1937{
1938 bool active = false;
1939 struct listnode *node = NULL;
1940 struct audio_usecase *uc = NULL;
1941 struct stream_out *curr_out = NULL;
1942
1943 list_for_each(node, &adev->usecase_list) {
1944 uc = node_to_item(node, struct audio_usecase, list);
1945 curr_out = (struct stream_out*) uc->stream.out;
1946
1947 if (curr_out && PCM_PLAYBACK == uc->type &&
1948 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1949 active = true;
1950 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301951 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301952 }
1953 }
1954 return active;
1955}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301956
1957static bool force_device_switch(struct audio_usecase *usecase)
1958{
1959 bool ret = false;
1960 bool is_it_true_mode = false;
1961
Zhou Song30f2c3e2018-02-08 14:02:15 +08001962 if (usecase->type == PCM_CAPTURE ||
1963 usecase->type == TRANSCODE_LOOPBACK) {
1964 return false;
1965 }
1966
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001967 if(usecase->stream.out == NULL) {
1968 ALOGE("%s: stream.out is NULL", __func__);
1969 return false;
1970 }
1971
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301972 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001973 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1974 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1975 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301976 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1977 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1978 (!is_it_true_mode && adev->native_playback_enabled)){
1979 ret = true;
1980 ALOGD("napb: time to toggle native mode");
1981 }
1982 }
1983
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301984 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301985 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1986 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001987 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301988 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301989 ALOGD("Force a2dp device switch to update new encoder config");
1990 ret = true;
1991 }
1992
Manish Dewangan671a4202017-08-18 17:30:46 +05301993 if (usecase->stream.out->stream_config_changed) {
1994 ALOGD("Force stream_config_changed to update iec61937 transmission config");
1995 return true;
1996 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301997 return ret;
1998}
1999
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302000bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2001{
2002 bool ret=false;
2003 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2004 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2005 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2006 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2007 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2008 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2009 ret = true;
2010
2011 return ret;
2012}
2013
2014bool is_a2dp_device(snd_device_t out_snd_device)
2015{
2016 bool ret=false;
2017 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2018 ret = true;
2019
2020 return ret;
2021}
2022
2023bool is_bt_soc_on(struct audio_device *adev)
2024{
2025 struct mixer_ctl *ctl;
2026 char *mixer_ctl_name = "BT SOC status";
2027 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2028 bool bt_soc_status = true;
2029 if (!ctl) {
2030 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2031 __func__, mixer_ctl_name);
2032 /*This is to ensure we dont break targets which dont have the kernel change*/
2033 return true;
2034 }
2035 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2036 ALOGD("BT SOC status: %d",bt_soc_status);
2037 return bt_soc_status;
2038}
2039
2040int out_standby_l(struct audio_stream *stream);
2041
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002042int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002044 snd_device_t out_snd_device = SND_DEVICE_NONE;
2045 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002046 struct audio_usecase *usecase = NULL;
2047 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002048 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002049 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302050 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002051 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002052 int status = 0;
Weiyin Jiang5d608082018-02-01 17:24:33 +08002053 audio_devices_t audio_device;
2054 audio_channel_mask_t channel_mask;
2055 int sample_rate;
2056 int acdb_id;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302058 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2059
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002060 usecase = get_usecase_from_list(adev, uc_id);
2061 if (usecase == NULL) {
2062 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2063 return -EINVAL;
2064 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002066 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002067 (usecase->type == VOIP_CALL) ||
2068 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302069 if(usecase->stream.out == NULL) {
2070 ALOGE("%s: stream.out is NULL", __func__);
2071 return -EINVAL;
2072 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002073 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002074 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002075 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002076 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302077 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
2078 if (usecase->stream.inout == NULL) {
2079 ALOGE("%s: stream.inout is NULL", __func__);
2080 return -EINVAL;
2081 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302082 stream_out.devices = usecase->stream.inout->out_config.devices;
2083 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2084 stream_out.format = usecase->stream.inout->out_config.format;
2085 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2086 out_snd_device = platform_get_output_snd_device(adev->platform,
2087 &stream_out);
2088 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302089 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002090 } else {
2091 /*
2092 * If the voice call is active, use the sound devices of voice call usecase
2093 * so that it would not result any device switch. All the usecases will
2094 * be switched to new device when select_devices() is called for voice call
2095 * usecase. This is to avoid switching devices for voice call when
2096 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002097 * choose voice call device only if the use case device is
2098 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002099 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002100 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002101 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002102 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002103 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2104 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302105 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2106 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002107 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002108 in_snd_device = vc_usecase->in_snd_device;
2109 out_snd_device = vc_usecase->out_snd_device;
2110 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002111 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002112 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002113 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002114 if ((voip_usecase != NULL) &&
2115 (usecase->type == PCM_PLAYBACK) &&
2116 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002117 out_snd_device_backend_match = platform_check_backends_match(
2118 voip_usecase->out_snd_device,
2119 platform_get_output_snd_device(
2120 adev->platform,
2121 usecase->stream.out));
2122 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002123 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002124 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2125 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002126 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002127 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002128 in_snd_device = voip_usecase->in_snd_device;
2129 out_snd_device = voip_usecase->out_snd_device;
2130 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002131 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002132 hfp_ucid = audio_extn_hfp_get_usecase();
2133 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002134 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002135 in_snd_device = hfp_usecase->in_snd_device;
2136 out_snd_device = hfp_usecase->out_snd_device;
2137 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002138 }
2139 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302140 if (usecase->stream.out == NULL) {
2141 ALOGE("%s: stream.out is NULL", __func__);
2142 return -EINVAL;
2143 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002144 usecase->devices = usecase->stream.out->devices;
2145 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002146 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002147 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002148 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002149 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2150 if (voip_usecase == NULL)
2151 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2152
2153 if ((usecase->stream.out != NULL &&
2154 voip_usecase != NULL &&
2155 usecase->stream.out->usecase == voip_usecase->id) &&
2156 adev->active_input &&
2157 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002158 select_devices(adev, adev->active_input->usecase);
2159 }
2160 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002161 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302162 if (usecase->stream.in == NULL) {
2163 ALOGE("%s: stream.in is NULL", __func__);
2164 return -EINVAL;
2165 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002166 usecase->devices = usecase->stream.in->device;
2167 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002168 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002169 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002170 if (adev->active_input &&
2171 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302172 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002173 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2174 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2175 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2176 out_device = voip_usecase->stream.out->devices;
2177 else if (adev->primary_output && !adev->primary_output->standby)
2178 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002179 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002180 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2181 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002182 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002183 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002184 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002185 }
2186 }
2187
2188 if (out_snd_device == usecase->out_snd_device &&
2189 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302190
2191 if (!force_device_switch(usecase))
2192 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002193 }
2194
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302195 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
2196 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
2197 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2198 return 0;
2199 }
2200
sangwoobc677242013-08-08 16:53:43 +09002201 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07002202 out_snd_device, platform_get_snd_device_name(out_snd_device),
2203 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002204
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002205 /*
2206 * Limitation: While in call, to do a device switch we need to disable
2207 * and enable both RX and TX devices though one of them is same as current
2208 * device.
2209 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002210 if ((usecase->type == VOICE_CALL) &&
2211 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2212 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002213 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002214 }
2215
2216 if (((usecase->type == VOICE_CALL) ||
2217 (usecase->type == VOIP_CALL)) &&
2218 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2219 /* Disable sidetone only if voice/voip call already exists */
2220 if (voice_is_call_state_active(adev) ||
2221 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002222 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002223
2224 /* Disable aanc only if voice call exists */
2225 if (voice_is_call_state_active(adev))
2226 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002227 }
2228
Zhou Songc66eb7e2017-08-08 18:29:07 +08002229 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302230 (!audio_extn_a2dp_is_ready())) {
2231 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002232 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302233 }
2234
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002235 /* Disable current sound devices */
2236 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002237 disable_audio_route(adev, usecase);
2238 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239 }
2240
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002241 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002242 disable_audio_route(adev, usecase);
2243 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244 }
2245
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002246 /* Applicable only on the targets that has external modem.
2247 * New device information should be sent to modem before enabling
2248 * the devices to reduce in-call device switch time.
2249 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002250 if ((usecase->type == VOICE_CALL) &&
2251 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2252 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002253 status = platform_switch_voice_call_enable_device_config(adev->platform,
2254 out_snd_device,
2255 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002256 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002257
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002258 /* Enable new sound devices */
2259 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002260 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302261 if (platform_check_codec_asrc_support(adev->platform))
2262 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002263 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002264 }
2265
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002266 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302267 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002268 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002269 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002270
Avinash Vaish71a8b972014-07-24 15:36:33 +05302271 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002272 status = platform_switch_voice_call_device_post(adev->platform,
2273 out_snd_device,
2274 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302275 enable_audio_route_for_voice_usecases(adev, usecase);
2276 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002277
sangwoo170731f2013-06-08 15:36:36 +09002278 usecase->in_snd_device = in_snd_device;
2279 usecase->out_snd_device = out_snd_device;
2280
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302281 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2282 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302283 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002284 if ((24 == usecase->stream.out->bit_width) &&
2285 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2286 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2287 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2288 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2289 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2290 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2291 /*
2292 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2293 * configured device sample rate, if not update the COPP rate to be equal to the
2294 * device sample rate, else open COPP at stream sample rate
2295 */
2296 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2297 usecase->stream.out->sample_rate,
2298 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302299 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2300 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002301 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2302 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2303 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2304 }
2305
Weiyin Jiang5d608082018-02-01 17:24:33 +08002306 /* Cache stream information to be notified to gef clients */
2307 audio_device = usecase->stream.out->devices;
2308 channel_mask = usecase->stream.out->channel_mask;
2309 sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
2310 acdb_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302311 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002312 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002313
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002314 /* If input stream is already running then effect needs to be
2315 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002316 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2317 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002318 check_and_enable_effect(adev);
2319
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002320 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002321 /* Enable aanc only if voice call exists */
2322 if (voice_is_call_state_active(adev))
2323 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2324
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002325 /* Enable sidetone only if other voice/voip call already exists */
2326 if (voice_is_call_state_active(adev) ||
2327 voice_extn_compress_voip_is_started(adev))
2328 voice_set_sidetone(adev, out_snd_device, true);
2329 }
2330
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002331 /* Applicable only on the targets that has external modem.
2332 * Enable device command should be sent to modem only after
2333 * enabling voice call mixer controls
2334 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002335 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002336 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2337 out_snd_device,
2338 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302339
2340 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2341
2342 if (usecase->type == VOIP_CALL) {
2343 if (adev->active_input != NULL &&
2344 !adev->active_input->standby) {
2345 if (is_bt_soc_on(adev) == false){
2346 ALOGD("BT SCO MIC disconnected while in connection");
2347 if (adev->active_input->pcm != NULL)
2348 pcm_stop(adev->active_input->pcm);
2349 }
2350 }
2351 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2352 && usecase->stream.out->started) {
2353 if (is_bt_soc_on(adev) == false) {
2354 ALOGD("BT SCO/A2DP disconnected while in connection");
2355 out_standby_l(&usecase->stream.out->stream.common);
2356 }
2357 }
2358 } else if ((usecase->stream.out != NULL) &&
2359 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2360 usecase->stream.out->started) {
2361 if (is_bt_soc_on(adev) == false) {
2362 ALOGD("BT SCO/A2dp disconnected while in connection");
2363 out_standby_l(&usecase->stream.out->stream.common);
2364 }
2365 }
2366 }
2367
Weiyin Jiang5d608082018-02-01 17:24:33 +08002368 /* Notify device change info to effect clients registered
2369 * NOTE: device lock has to be unlock temporarily here.
2370 * To the worst case, we notify stale info to clients.
2371 */
2372 if (usecase->type == PCM_PLAYBACK) {
2373 pthread_mutex_unlock(&adev->lock);
2374 audio_extn_gef_notify_device_config(audio_device, channel_mask, sample_rate, acdb_id);
2375 pthread_mutex_lock(&adev->lock);
2376 }
2377
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302378 ALOGD("%s: done",__func__);
2379
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002380 return status;
2381}
2382
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002383static int stop_input_stream(struct stream_in *in)
2384{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302385 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302387
2388 if (in == NULL) {
2389 ALOGE("%s: stream_in ptr is NULL", __func__);
2390 return -EINVAL;
2391 }
2392
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002393 struct audio_device *adev = in->dev;
2394
Eric Laurent994a6932013-07-17 11:51:42 -07002395 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002396 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002397 uc_info = get_usecase_from_list(adev, in->usecase);
2398 if (uc_info == NULL) {
2399 ALOGE("%s: Could not find the usecase (%d) in the list",
2400 __func__, in->usecase);
2401 return -EINVAL;
2402 }
2403
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002404 /* Close in-call recording streams */
2405 voice_check_and_stop_incall_rec_usecase(adev, in);
2406
Eric Laurent150dbfe2013-02-27 14:31:02 -08002407 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002408 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002409
2410 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002411 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002413 list_remove(&uc_info->list);
2414 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002416 adev->active_input = get_next_active_input(adev);
2417
Eric Laurent994a6932013-07-17 11:51:42 -07002418 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002419 return ret;
2420}
2421
2422int start_input_stream(struct stream_in *in)
2423{
2424 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002425 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302427
2428 if (in == NULL) {
2429 ALOGE("%s: stream_in ptr is NULL", __func__);
2430 return -EINVAL;
2431 }
2432
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002434 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002435 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002436
Mingming Yin2664a5b2015-09-03 10:53:11 -07002437 if (get_usecase_from_list(adev, usecase) == NULL)
2438 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302439 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2440 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002441
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302442 if (CARD_STATUS_OFFLINE == in->card_status||
2443 CARD_STATUS_OFFLINE == adev->card_status) {
2444 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302445 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302446 goto error_config;
2447 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302448
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302449 if (audio_is_bluetooth_sco_device(in->device)) {
2450 if (!adev->bt_sco_on) {
2451 ALOGE("%s: SCO profile is not ready, return error", __func__);
2452 ret = -EIO;
2453 goto error_config;
2454 }
2455 }
2456
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002457 /* Check if source matches incall recording usecase criteria */
2458 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2459 if (ret)
2460 goto error_config;
2461 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002462 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2463
2464 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2465 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2466 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002467 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002468 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002469
Eric Laurentb23d5282013-05-14 15:27:20 -07002470 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002471 if (in->pcm_device_id < 0) {
2472 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2473 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002474 ret = -EINVAL;
2475 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002477
2478 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002479 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002480
2481 if (!uc_info) {
2482 ret = -ENOMEM;
2483 goto error_config;
2484 }
2485
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486 uc_info->id = in->usecase;
2487 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002488 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002489 uc_info->devices = in->device;
2490 uc_info->in_snd_device = SND_DEVICE_NONE;
2491 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002493 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302494 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2495 adev->perf_lock_opts,
2496 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002497 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498
Haynes Mathew George16081042017-05-31 17:16:49 -07002499 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302500 ret = audio_extn_cin_start_input_stream(in);
2501 if (ret)
2502 goto error_open;
2503 else
2504 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002505 }
2506
Haynes Mathew George16081042017-05-31 17:16:49 -07002507 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002508 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002509 ALOGE("%s: pcm stream not ready", __func__);
2510 goto error_open;
2511 }
2512 ret = pcm_start(in->pcm);
2513 if (ret < 0) {
2514 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2515 goto error_open;
2516 }
2517 } else {
2518 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2519 unsigned int pcm_open_retry_count = 0;
2520
2521 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2522 flags |= PCM_MMAP | PCM_NOIRQ;
2523 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2524 } else if (in->realtime) {
2525 flags |= PCM_MMAP | PCM_NOIRQ;
2526 }
2527
Garmond Leunge2433c32017-09-28 21:51:22 -07002528 if (audio_extn_ffv_get_stream() == in) {
2529 ALOGD("%s: ffv stream, update pcm config", __func__);
2530 audio_extn_ffv_update_pcm_config(&config);
2531 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002532 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2533 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2534
2535 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002536 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002537 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002538 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002539 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002540 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2541 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2542 if (in->pcm != NULL) {
2543 pcm_close(in->pcm);
2544 in->pcm = NULL;
2545 }
2546 if (pcm_open_retry_count-- == 0) {
2547 ret = -EIO;
2548 goto error_open;
2549 }
2550 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2551 continue;
2552 }
2553 break;
2554 }
2555
2556 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002557 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002558 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002559 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002560 if (ret < 0) {
2561 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2562 pcm_close(in->pcm);
2563 in->pcm = NULL;
2564 goto error_open;
2565 }
2566 register_in_stream(in);
2567 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002568 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002569 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002570 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002571 if (ret < 0) {
2572 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002573 pcm_close(in->pcm);
2574 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002575 goto error_open;
2576 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002577 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002578 }
2579
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002580 check_and_enable_effect(adev);
2581
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302582done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302583 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002584 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002585
Eric Laurentc8400632013-02-14 19:04:54 -08002586 return ret;
2587
2588error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302589 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002591error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302592 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302593 /*
2594 * sleep 50ms to allow sufficient time for kernel
2595 * drivers to recover incases like SSR.
2596 */
2597 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002598 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002599
2600 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601}
2602
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002603void lock_input_stream(struct stream_in *in)
2604{
2605 pthread_mutex_lock(&in->pre_lock);
2606 pthread_mutex_lock(&in->lock);
2607 pthread_mutex_unlock(&in->pre_lock);
2608}
2609
2610void lock_output_stream(struct stream_out *out)
2611{
2612 pthread_mutex_lock(&out->pre_lock);
2613 pthread_mutex_lock(&out->lock);
2614 pthread_mutex_unlock(&out->pre_lock);
2615}
2616
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002617/* must be called with out->lock locked */
2618static int send_offload_cmd_l(struct stream_out* out, int command)
2619{
2620 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2621
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002622 if (!cmd) {
2623 ALOGE("failed to allocate mem for command 0x%x", command);
2624 return -ENOMEM;
2625 }
2626
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002627 ALOGVV("%s %d", __func__, command);
2628
2629 cmd->cmd = command;
2630 list_add_tail(&out->offload_cmd_list, &cmd->node);
2631 pthread_cond_signal(&out->offload_cond);
2632 return 0;
2633}
2634
2635/* must be called iwth out->lock locked */
2636static void stop_compressed_output_l(struct stream_out *out)
2637{
2638 out->offload_state = OFFLOAD_STATE_IDLE;
2639 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002640 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002641 if (out->compr != NULL) {
2642 compress_stop(out->compr);
2643 while (out->offload_thread_blocked) {
2644 pthread_cond_wait(&out->cond, &out->lock);
2645 }
2646 }
2647}
2648
Varun Balaraje49253e2017-07-06 19:48:56 +05302649bool is_interactive_usecase(audio_usecase_t uc_id)
2650{
2651 unsigned int i;
2652 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2653 if (uc_id == interactive_usecases[i])
2654 return true;
2655 }
2656 return false;
2657}
2658
2659static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2660{
2661 audio_usecase_t ret_uc = USECASE_INVALID;
2662 unsigned int intract_uc_index;
2663 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2664
2665 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2666 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2667 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2668 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2669 ret_uc = interactive_usecases[intract_uc_index];
2670 break;
2671 }
2672 }
2673
2674 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2675 return ret_uc;
2676}
2677
2678static void free_interactive_usecase(struct audio_device *adev,
2679 audio_usecase_t uc_id)
2680{
2681 unsigned int interact_uc_index;
2682 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2683
2684 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2685 if (interactive_usecases[interact_uc_index] == uc_id) {
2686 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2687 break;
2688 }
2689 }
2690 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2691}
2692
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002693bool is_offload_usecase(audio_usecase_t uc_id)
2694{
2695 unsigned int i;
2696 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2697 if (uc_id == offload_usecases[i])
2698 return true;
2699 }
2700 return false;
2701}
2702
Dhananjay Kumarac341582017-02-23 23:42:25 +05302703static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002704{
vivek mehta446c3962015-09-14 10:57:35 -07002705 audio_usecase_t ret_uc = USECASE_INVALID;
2706 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002707 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002708 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302709 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002710 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2711 else
2712 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002713
vivek mehta446c3962015-09-14 10:57:35 -07002714 pthread_mutex_lock(&adev->lock);
2715 if (get_usecase_from_list(adev, ret_uc) != NULL)
2716 ret_uc = USECASE_INVALID;
2717 pthread_mutex_unlock(&adev->lock);
2718
2719 return ret_uc;
2720 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002721
2722 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002723 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2724 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2725 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2726 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002727 break;
2728 }
2729 }
vivek mehta446c3962015-09-14 10:57:35 -07002730
2731 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2732 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002733}
2734
2735static void free_offload_usecase(struct audio_device *adev,
2736 audio_usecase_t uc_id)
2737{
vivek mehta446c3962015-09-14 10:57:35 -07002738 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002739 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002740
2741 if (!adev->multi_offload_enable)
2742 return;
2743
2744 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2745 if (offload_usecases[offload_uc_index] == uc_id) {
2746 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002747 break;
2748 }
2749 }
2750 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2751}
2752
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002753static void *offload_thread_loop(void *context)
2754{
2755 struct stream_out *out = (struct stream_out *) context;
2756 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002757 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002758
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002759 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2760 set_sched_policy(0, SP_FOREGROUND);
2761 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2762
2763 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002764 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002765 for (;;) {
2766 struct offload_cmd *cmd = NULL;
2767 stream_callback_event_t event;
2768 bool send_callback = false;
2769
2770 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2771 __func__, list_empty(&out->offload_cmd_list),
2772 out->offload_state);
2773 if (list_empty(&out->offload_cmd_list)) {
2774 ALOGV("%s SLEEPING", __func__);
2775 pthread_cond_wait(&out->offload_cond, &out->lock);
2776 ALOGV("%s RUNNING", __func__);
2777 continue;
2778 }
2779
2780 item = list_head(&out->offload_cmd_list);
2781 cmd = node_to_item(item, struct offload_cmd, node);
2782 list_remove(item);
2783
2784 ALOGVV("%s STATE %d CMD %d out->compr %p",
2785 __func__, out->offload_state, cmd->cmd, out->compr);
2786
2787 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2788 free(cmd);
2789 break;
2790 }
2791
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002792 // allow OFFLOAD_CMD_ERROR reporting during standby
2793 // this is needed to handle failures during compress_open
2794 // Note however that on a pause timeout, the stream is closed
2795 // and no offload usecase will be active. Therefore this
2796 // special case is needed for compress_open failures alone
2797 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2798 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002799 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002800 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002801 pthread_cond_signal(&out->cond);
2802 continue;
2803 }
2804 out->offload_thread_blocked = true;
2805 pthread_mutex_unlock(&out->lock);
2806 send_callback = false;
2807 switch(cmd->cmd) {
2808 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002809 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002810 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002811 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002812 send_callback = true;
2813 event = STREAM_CBK_EVENT_WRITE_READY;
2814 break;
2815 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002816 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302817 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002818 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302819 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002820 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302821 if (ret < 0)
2822 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302823 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302824 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002825 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002826 else
2827 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002828 if (-ENETRESET != ret && !(-EINTR == ret &&
2829 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302830 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302831 pthread_mutex_lock(&out->lock);
2832 out->send_new_metadata = 1;
2833 out->send_next_track_params = true;
2834 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302835 event = STREAM_CBK_EVENT_DRAIN_READY;
2836 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2837 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302838 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002839 break;
2840 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002841 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002842 ret = compress_drain(out->compr);
2843 ALOGD("copl(%p):out of compress_drain", out);
2844 // EINTR check avoids drain interruption due to SSR
2845 if (-ENETRESET != ret && !(-EINTR == ret &&
2846 CARD_STATUS_OFFLINE == out->card_status)) {
2847 send_callback = true;
2848 event = STREAM_CBK_EVENT_DRAIN_READY;
2849 } else
2850 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002851 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302852 case OFFLOAD_CMD_ERROR:
2853 ALOGD("copl(%p): sending error callback to AF", out);
2854 send_callback = true;
2855 event = STREAM_CBK_EVENT_ERROR;
2856 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002857 default:
2858 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2859 break;
2860 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002861 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002862 out->offload_thread_blocked = false;
2863 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002864 if (send_callback && out->client_callback) {
2865 ALOGVV("%s: sending client_callback event %d", __func__, event);
2866 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002867 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002868 free(cmd);
2869 }
2870
2871 pthread_cond_signal(&out->cond);
2872 while (!list_empty(&out->offload_cmd_list)) {
2873 item = list_head(&out->offload_cmd_list);
2874 list_remove(item);
2875 free(node_to_item(item, struct offload_cmd, node));
2876 }
2877 pthread_mutex_unlock(&out->lock);
2878
2879 return NULL;
2880}
2881
2882static int create_offload_callback_thread(struct stream_out *out)
2883{
2884 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2885 list_init(&out->offload_cmd_list);
2886 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2887 offload_thread_loop, out);
2888 return 0;
2889}
2890
2891static int destroy_offload_callback_thread(struct stream_out *out)
2892{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002893 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002894 stop_compressed_output_l(out);
2895 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2896
2897 pthread_mutex_unlock(&out->lock);
2898 pthread_join(out->offload_thread, (void **) NULL);
2899 pthread_cond_destroy(&out->offload_cond);
2900
2901 return 0;
2902}
2903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002904static int stop_output_stream(struct stream_out *out)
2905{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302906 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002907 struct audio_usecase *uc_info;
2908 struct audio_device *adev = out->dev;
2909
Eric Laurent994a6932013-07-17 11:51:42 -07002910 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002911 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002912 uc_info = get_usecase_from_list(adev, out->usecase);
2913 if (uc_info == NULL) {
2914 ALOGE("%s: Could not find the usecase (%d) in the list",
2915 __func__, out->usecase);
2916 return -EINVAL;
2917 }
2918
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002919 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302920 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002921 if (adev->visualizer_stop_output != NULL)
2922 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002923
2924 audio_extn_dts_remove_state_notifier_node(out->usecase);
2925
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002926 if (adev->offload_effects_stop_output != NULL)
2927 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2928 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002929
Arun Mirpurief53ce52018-09-11 18:00:09 -07002930 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2931 voice_set_device_mute_flag(adev, false);
2932
Eric Laurent150dbfe2013-02-27 14:31:02 -08002933 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002934 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002935
2936 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002937 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002939 if (is_offload_usecase(out->usecase)) {
2940 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2941 adev->dsp_bit_width_enforce_mode,
2942 false);
2943 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07002944 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2945 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
2946 false);
2947
2948 if (ret != 0)
2949 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
2950 /* default service interval was successfully updated,
2951 reopen USB backend with new service interval */
2952 ret = 0;
2953 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002954
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002955 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302956 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002957 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302958 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002959 ALOGV("Disable passthrough , reset mixer to pcm");
2960 /* NO_PASSTHROUGH */
2961 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002962 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002963 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2964 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002965
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302966 /* Must be called after removing the usecase from list */
2967 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05302968 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302969
Manish Dewangan21a850a2017-08-14 12:03:55 +05302970 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002971 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2972 if (ret < 0)
2973 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2974 }
2975
Garmond Leung5fd0b552018-04-17 11:56:12 -07002976 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002977 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002978 return ret;
2979}
2980
2981int start_output_stream(struct stream_out *out)
2982{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002984 struct audio_usecase *uc_info;
2985 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002986 char mixer_ctl_name[128];
2987 struct mixer_ctl *ctl = NULL;
2988 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302989 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990
Haynes Mathew George380745d2017-10-04 15:27:45 -07002991 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002992 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2993 ret = -EINVAL;
2994 goto error_config;
2995 }
2996
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302997 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2998 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2999 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303000
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303001 if (CARD_STATUS_OFFLINE == out->card_status ||
3002 CARD_STATUS_OFFLINE == adev->card_status) {
3003 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303004 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303005 goto error_config;
3006 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303007
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303008 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
3009 if (!audio_extn_a2dp_is_ready()) {
3010 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303011 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303012 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303013 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3014 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3015 ret = -EAGAIN;
3016 goto error_config;
3017 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303018 }
3019 }
3020 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303021 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3022 if (!adev->bt_sco_on) {
3023 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3024 //combo usecase just by pass a2dp
3025 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3026 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3027 } else {
3028 ALOGE("%s: SCO profile is not ready, return error", __func__);
3029 ret = -EAGAIN;
3030 goto error_config;
3031 }
3032 }
3033 }
3034
Eric Laurentb23d5282013-05-14 15:27:20 -07003035 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036 if (out->pcm_device_id < 0) {
3037 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3038 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003039 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003040 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003041 }
3042
3043 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003044
3045 if (!uc_info) {
3046 ret = -ENOMEM;
3047 goto error_config;
3048 }
3049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 uc_info->id = out->usecase;
3051 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003052 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003053 uc_info->devices = out->devices;
3054 uc_info->in_snd_device = SND_DEVICE_NONE;
3055 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003056
3057 /* This must be called before adding this usecase to the list */
3058 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3059 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3060 /* USB backend is not reopened immediately.
3061 This is eventually done as part of select_devices */
3062 }
3063
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003064 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303066 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3067 adev->perf_lock_opts,
3068 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303069
3070 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303071 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303072 if (audio_extn_passthru_is_enabled() &&
3073 audio_extn_passthru_is_passthrough_stream(out)) {
3074 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303075 }
3076 }
3077
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303078 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3079 (!audio_extn_a2dp_is_ready())) {
3080 if (!a2dp_combo) {
3081 check_a2dp_restore_l(adev, out, false);
3082 } else {
3083 audio_devices_t dev = out->devices;
3084 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3085 select_devices(adev, out->usecase);
3086 out->devices = dev;
3087 }
3088 } else {
3089 select_devices(adev, out->usecase);
3090 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003091
Arun Mirpurief53ce52018-09-11 18:00:09 -07003092 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3093 voice_set_device_mute_flag(adev, true);
3094
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003095 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3096 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003097
3098 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3099 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3100 ALOGE("%s: pcm stream not ready", __func__);
3101 goto error_open;
3102 }
3103 ret = pcm_start(out->pcm);
3104 if (ret < 0) {
3105 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3106 goto error_open;
3107 }
3108 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003109 unsigned int flags = PCM_OUT;
3110 unsigned int pcm_open_retry_count = 0;
3111 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3112 flags |= PCM_MMAP | PCM_NOIRQ;
3113 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003114 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003115 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003116 } else
3117 flags |= PCM_MONOTONIC;
3118
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003119 if ((adev->vr_audio_mode_enabled) &&
3120 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3121 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3122 "PCM_Dev %d Topology", out->pcm_device_id);
3123 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3124 if (!ctl) {
3125 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3126 __func__, mixer_ctl_name);
3127 } else {
3128 //if success use ULLPP
3129 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3130 __func__, mixer_ctl_name, out->pcm_device_id);
3131 //There is a still a possibility that some sessions
3132 // that request for FAST|RAW when 3D audio is active
3133 //can go through ULLPP. Ideally we expects apps to
3134 //listen to audio focus and stop concurrent playback
3135 //Also, we will look for mode flag (voice_in_communication)
3136 //before enabling the realtime flag.
3137 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3138 }
3139 }
3140
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003141 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003142 ATRACE_BEGIN("pcm_open");
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003143 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3144 flags, &out->config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003145 ATRACE_END();
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003146 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3147 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3148 if (out->pcm != NULL) {
3149 pcm_close(out->pcm);
3150 out->pcm = NULL;
3151 }
3152 if (pcm_open_retry_count-- == 0) {
3153 ret = -EIO;
3154 goto error_open;
3155 }
3156 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3157 continue;
3158 }
3159 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003160 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003161
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003162 ALOGV("%s: pcm_prepare", __func__);
3163 if (pcm_is_ready(out->pcm)) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003164 ATRACE_BEGIN("pcm_prepare");
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003165 ret = pcm_prepare(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003166 ATRACE_END();
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003167 if (ret < 0) {
3168 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3169 pcm_close(out->pcm);
3170 out->pcm = NULL;
3171 goto error_open;
3172 }
3173 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05303174 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303175 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08003176 // apply volume for voip playback after path is set up
3177 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3178 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003179 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003180 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303181 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003182 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3183 adev->dsp_bit_width_enforce_mode,
3184 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003186 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003187 out->compr = compress_open(adev->snd_card,
3188 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003189 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003190 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003191 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003192 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003193 compress_close(out->compr);
3194 out->compr = NULL;
3195 ret = -EIO;
3196 goto error_open;
3197 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303198 /* compress_open sends params of the track, so reset the flag here */
3199 out->is_compr_metadata_avail = false;
3200
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003201 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003202 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003203
Fred Oh3f43e742015-03-04 18:42:34 -08003204 /* Since small bufs uses blocking writes, a write will be blocked
3205 for the default max poll time (20s) in the event of an SSR.
3206 Reduce the poll time to observe and deal with SSR faster.
3207 */
Ashish Jain5106d362016-05-11 19:23:33 +05303208 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003209 compress_set_max_poll_wait(out->compr, 1000);
3210 }
3211
Manish Dewangan69426c82017-01-30 17:35:36 +05303212 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303213 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303214
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003215 audio_extn_dts_create_state_notifier_node(out->usecase);
3216 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3217 popcount(out->channel_mask),
3218 out->playback_started);
3219
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003220#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303221 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003222 audio_extn_dolby_send_ddp_endp_params(adev);
3223#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303224 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3225 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003226 if (adev->visualizer_start_output != NULL)
3227 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3228 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303229 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003230 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003231 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003232 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003233
3234 if (ret == 0) {
3235 register_out_stream(out);
3236 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003237 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3238 ALOGE("%s: pcm stream not ready", __func__);
3239 goto error_open;
3240 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003241 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003242 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003243 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003244 if (ret < 0)
3245 goto error_open;
3246 }
3247 }
3248
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303249 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003250 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003251
Manish Dewangan21a850a2017-08-14 12:03:55 +05303252 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003253 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003254 if (ret < 0)
3255 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3256 }
3257
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003258 // consider a scenario where on pause lower layers are tear down.
3259 // so on resume, swap mixer control need to be sent only when
3260 // backend is active, hence rather than sending from enable device
3261 // sending it from start of streamtream
3262
3263 platform_set_swap_channels(adev, true);
3264
Haynes Mathew George380745d2017-10-04 15:27:45 -07003265 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003266 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003267error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303268 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003270error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303271 /*
3272 * sleep 50ms to allow sufficient time for kernel
3273 * drivers to recover incases like SSR.
3274 */
3275 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003276 ATRACE_END();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003277 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278}
3279
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003280static int check_input_parameters(uint32_t sample_rate,
3281 audio_format_t format,
3282 int channel_count)
3283{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003284 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303286 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3287 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3288 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003289 !voice_extn_compress_voip_is_format_supported(format) &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003290 !audio_extn_compr_cap_format_supported(format))
3291 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003292
3293 switch (channel_count) {
3294 case 1:
3295 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303296 case 3:
3297 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003298 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003299 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003300 break;
3301 default:
3302 ret = -EINVAL;
3303 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304
3305 switch (sample_rate) {
3306 case 8000:
3307 case 11025:
3308 case 12000:
3309 case 16000:
3310 case 22050:
3311 case 24000:
3312 case 32000:
3313 case 44100:
3314 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003315 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303316 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003317 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303318 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319 break;
3320 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003321 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322 }
3323
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003324 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325}
3326
Naresh Tanniru04f71882018-06-26 17:46:22 +05303327
3328/** Add a value in a list if not already present.
3329 * @return true if value was successfully inserted or already present,
3330 * false if the list is full and does not contain the value.
3331 */
3332static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3333 for (size_t i = 0; i < list_length; i++) {
3334 if (list[i] == value) return true; // value is already present
3335 if (list[i] == 0) { // no values in this slot
3336 list[i] = value;
3337 return true; // value inserted
3338 }
3339 }
3340 return false; // could not insert value
3341}
3342
3343/** Add channel_mask in supported_channel_masks if not already present.
3344 * @return true if channel_mask was successfully inserted or already present,
3345 * false if supported_channel_masks is full and does not contain channel_mask.
3346 */
3347static void register_channel_mask(audio_channel_mask_t channel_mask,
3348 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3349 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3350 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3351}
3352
3353/** Add format in supported_formats if not already present.
3354 * @return true if format was successfully inserted or already present,
3355 * false if supported_formats is full and does not contain format.
3356 */
3357static void register_format(audio_format_t format,
3358 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3359 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3360 "%s: stream can not declare supporting its format %x", __func__, format);
3361}
3362/** Add sample_rate in supported_sample_rates if not already present.
3363 * @return true if sample_rate was successfully inserted or already present,
3364 * false if supported_sample_rates is full and does not contain sample_rate.
3365 */
3366static void register_sample_rate(uint32_t sample_rate,
3367 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3368 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3369 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3370}
3371
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372static size_t get_input_buffer_size(uint32_t sample_rate,
3373 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003374 int channel_count,
3375 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376{
3377 size_t size = 0;
3378
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003379 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3380 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003382 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003383 if (is_low_latency)
3384 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303385
3386 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003388 /* make sure the size is multiple of 32 bytes
3389 * At 48 kHz mono 16-bit PCM:
3390 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3391 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
3392 */
3393 size += 0x1f;
3394 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003395
3396 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397}
3398
Ashish Jain058165c2016-09-28 23:18:48 +05303399static size_t get_output_period_size(uint32_t sample_rate,
3400 audio_format_t format,
3401 int channel_count,
3402 int duration /*in millisecs*/)
3403{
3404 size_t size = 0;
3405 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3406
3407 if ((duration == 0) || (sample_rate == 0) ||
3408 (bytes_per_sample == 0) || (channel_count == 0)) {
3409 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3410 bytes_per_sample, channel_count);
3411 return -EINVAL;
3412 }
3413
3414 size = (sample_rate *
3415 duration *
3416 bytes_per_sample *
3417 channel_count) / 1000;
3418 /*
3419 * To have same PCM samples for all channels, the buffer size requires to
3420 * be multiple of (number of channels * bytes per sample)
3421 * For writes to succeed, the buffer must be written at address which is multiple of 32
3422 */
3423 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3424
3425 return (size/(channel_count * bytes_per_sample));
3426}
3427
Zhou Song48453a02018-01-10 17:50:59 +08003428static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303429{
3430 uint64_t actual_frames_rendered = 0;
3431 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3432
3433 /* This adjustment accounts for buffering after app processor.
3434 * It is based on estimated DSP latency per use case, rather than exact.
3435 */
3436 int64_t platform_latency = platform_render_latency(out->usecase) *
3437 out->sample_rate / 1000000LL;
3438
Zhou Song48453a02018-01-10 17:50:59 +08003439 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303440 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3441 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3442 * hence only estimate.
3443 */
3444 int64_t signed_frames = out->written - kernel_buffer_size;
3445
3446 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3447
Zhou Song48453a02018-01-10 17:50:59 +08003448 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303449 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003450 if (timestamp != NULL )
3451 *timestamp = out->writeAt;
3452 } else if (timestamp != NULL) {
3453 clock_gettime(CLOCK_MONOTONIC, timestamp);
3454 }
3455 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303456
3457 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3458 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3459 (long long int)out->written, (int)kernel_buffer_size,
3460 audio_bytes_per_sample(out->compr_config.codec->format),
3461 popcount(out->channel_mask));
3462
3463 return actual_frames_rendered;
3464}
3465
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3467{
3468 struct stream_out *out = (struct stream_out *)stream;
3469
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003470 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471}
3472
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003473static int out_set_sample_rate(struct audio_stream *stream __unused,
3474 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475{
3476 return -ENOSYS;
3477}
3478
3479static size_t out_get_buffer_size(const struct audio_stream *stream)
3480{
3481 struct stream_out *out = (struct stream_out *)stream;
3482
Varun Balaraje49253e2017-07-06 19:48:56 +05303483 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303484 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303485 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303486 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3487 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3488 else
3489 return out->compr_config.fragment_size;
3490 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003491 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003492 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3493 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 +05303494 else if (is_offload_usecase(out->usecase) &&
3495 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303496 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003497
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003498 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003499 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003500}
3501
3502static uint32_t out_get_channels(const struct audio_stream *stream)
3503{
3504 struct stream_out *out = (struct stream_out *)stream;
3505
3506 return out->channel_mask;
3507}
3508
3509static audio_format_t out_get_format(const struct audio_stream *stream)
3510{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003511 struct stream_out *out = (struct stream_out *)stream;
3512
3513 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514}
3515
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003516static int out_set_format(struct audio_stream *stream __unused,
3517 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518{
3519 return -ENOSYS;
3520}
3521
3522static int out_standby(struct audio_stream *stream)
3523{
3524 struct stream_out *out = (struct stream_out *)stream;
3525 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003526 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003527
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303528 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3529 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003531 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003532 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003533 if (adev->adm_deregister_stream)
3534 adev->adm_deregister_stream(adev->adm_data, out->handle);
3535
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003536 if (is_offload_usecase(out->usecase))
3537 stop_compressed_output_l(out);
3538
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003539 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003541 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3542 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303543 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003544 pthread_mutex_unlock(&adev->lock);
3545 pthread_mutex_unlock(&out->lock);
3546 ALOGD("VOIP output entered standby");
3547 return 0;
3548 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003549 if (out->pcm) {
3550 pcm_close(out->pcm);
3551 out->pcm = NULL;
3552 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003553 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3554 do_stop = out->playback_started;
3555 out->playback_started = false;
3556 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003557 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003558 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303559 out->send_next_track_params = false;
3560 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003561 out->gapless_mdata.encoder_delay = 0;
3562 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003563 if (out->compr != NULL) {
3564 compress_close(out->compr);
3565 out->compr = NULL;
3566 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003567 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003568 if (do_stop) {
3569 stop_output_stream(out);
3570 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003571 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572 }
3573 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303574 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003575 return 0;
3576}
3577
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303578static int out_on_error(struct audio_stream *stream)
3579{
3580 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003581 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303582
3583 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003584 // always send CMD_ERROR for offload streams, this
3585 // is needed e.g. when SSR happens within compress_open
3586 // since the stream is active, offload_callback_thread is also active.
3587 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3588 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003589 }
3590 pthread_mutex_unlock(&out->lock);
3591
3592 status = out_standby(&out->stream.common);
3593
3594 lock_output_stream(out);
3595 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003596 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303597 }
3598 pthread_mutex_unlock(&out->lock);
3599
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003600 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303601}
3602
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303603/*
3604 *standby implementation without locks, assumes that the callee already
3605 *has taken adev and out lock.
3606 */
3607int out_standby_l(struct audio_stream *stream)
3608{
3609 struct stream_out *out = (struct stream_out *)stream;
3610 struct audio_device *adev = out->dev;
3611
3612 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3613 stream, out->usecase, use_case_table[out->usecase]);
3614
3615 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003616 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303617 if (adev->adm_deregister_stream)
3618 adev->adm_deregister_stream(adev->adm_data, out->handle);
3619
3620 if (is_offload_usecase(out->usecase))
3621 stop_compressed_output_l(out);
3622
3623 out->standby = true;
3624 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3625 voice_extn_compress_voip_close_output_stream(stream);
3626 out->started = 0;
3627 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003628 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303629 return 0;
3630 } else if (!is_offload_usecase(out->usecase)) {
3631 if (out->pcm) {
3632 pcm_close(out->pcm);
3633 out->pcm = NULL;
3634 }
3635 } else {
3636 ALOGD("copl(%p):standby", out);
3637 out->send_next_track_params = false;
3638 out->is_compr_metadata_avail = false;
3639 out->gapless_mdata.encoder_delay = 0;
3640 out->gapless_mdata.encoder_padding = 0;
3641 if (out->compr != NULL) {
3642 compress_close(out->compr);
3643 out->compr = NULL;
3644 }
3645 }
3646 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003647 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303648 }
3649 ALOGD("%s: exit", __func__);
3650 return 0;
3651}
3652
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003653static int out_dump(const struct audio_stream *stream __unused,
3654 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655{
3656 return 0;
3657}
3658
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003659static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3660{
3661 int ret = 0;
3662 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003663
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003664 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003665 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003666 return -EINVAL;
3667 }
3668
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303669 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003670
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003671 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3672 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303673 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003674 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003675 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3676 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303677 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003678 }
3679
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003680 ALOGV("%s new encoder delay %u and padding %u", __func__,
3681 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3682
3683 return 0;
3684}
3685
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003686static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3687{
3688 return out == adev->primary_output || out == adev->voice_tx_output;
3689}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003690
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303691// note: this call is safe only if the stream_cb is
3692// removed first in close_output_stream (as is done now).
3693static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3694{
3695 if (!stream || !parms)
3696 return;
3697
3698 struct stream_out *out = (struct stream_out *)stream;
3699 struct audio_device *adev = out->dev;
3700
3701 card_status_t status;
3702 int card;
3703 if (parse_snd_card_status(parms, &card, &status) < 0)
3704 return;
3705
3706 pthread_mutex_lock(&adev->lock);
3707 bool valid_cb = (card == adev->snd_card);
3708 pthread_mutex_unlock(&adev->lock);
3709
3710 if (!valid_cb)
3711 return;
3712
3713 lock_output_stream(out);
3714 if (out->card_status != status)
3715 out->card_status = status;
3716 pthread_mutex_unlock(&out->lock);
3717
3718 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3719 use_case_table[out->usecase],
3720 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3721
3722 if (status == CARD_STATUS_OFFLINE)
3723 out_on_error(stream);
3724
3725 return;
3726}
3727
Kevin Rocardfce19002017-08-07 19:21:36 -07003728static int get_alive_usb_card(struct str_parms* parms) {
3729 int card;
3730 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
3731 !audio_extn_usb_alive(card)) {
3732 return card;
3733 }
3734 return -ENODEV;
3735}
3736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003737static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3738{
3739 struct stream_out *out = (struct stream_out *)stream;
3740 struct audio_device *adev = out->dev;
3741 struct str_parms *parms;
3742 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003743 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303744 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003745 bool reconfig = false;
3746 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747
sangwoobc677242013-08-08 16:53:43 +09003748 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003749 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303751 if (!parms)
3752 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003753 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3754 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003755 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003756 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003757 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003758
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003759 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003760 * When HDMI cable is unplugged the music playback is paused and
3761 * the policy manager sends routing=0. But the audioflinger continues
3762 * to write data until standby time (3sec). As the HDMI core is
3763 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003764 * Avoid this by routing audio to speaker until standby.
3765 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003766 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3767 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303768 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003769 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3770 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003771 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303772 /*
3773 * When A2DP is disconnected the
3774 * music playback is paused and the policy manager sends routing=0
3775 * But the audioflingercontinues to write data until standby time
3776 * (3sec). As BT is turned off, the write gets blocked.
3777 * Avoid this by routing audio to speaker until standby.
3778 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003779 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07003780 (val == AUDIO_DEVICE_NONE) &&
3781 !audio_extn_a2dp_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303782 val = AUDIO_DEVICE_OUT_SPEAKER;
3783 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05303784 /*
3785 * When USB headset is disconnected the music platback paused
3786 * and the policy manager send routing=0. But if the USB is connected
3787 * back before the standby time, AFE is not closed and opened
3788 * when USB is connected back. So routing to speker will guarantee
3789 * AFE reconfiguration and AFE will be opend once USB is connected again
3790 */
3791 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
3792 (val == AUDIO_DEVICE_NONE) &&
3793 !audio_extn_usb_connected(parms)) {
3794 val = AUDIO_DEVICE_OUT_SPEAKER;
3795 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303796 /* To avoid a2dp to sco overlapping / BT device improper state
3797 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303798 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303799 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3800 if (!audio_extn_a2dp_is_ready()) {
3801 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3802 //combo usecase just by pass a2dp
3803 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303804 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303805 } else {
3806 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3807 /* update device to a2dp and don't route as BT returned error
3808 * However it is still possible a2dp routing called because
3809 * of current active device disconnection (like wired headset)
3810 */
3811 out->devices = val;
3812 pthread_mutex_unlock(&out->lock);
3813 pthread_mutex_unlock(&adev->lock);
3814 goto error;
3815 }
3816 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303817 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003818
3819 audio_devices_t new_dev = val;
3820
3821 // Workaround: If routing to an non existing usb device, fail gracefully
3822 // The routing request will otherwise block during 10 second
3823 int card;
3824 if (audio_is_usb_out_device(new_dev) &&
3825 (card = get_alive_usb_card(parms)) >= 0) {
3826
3827 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
3828 pthread_mutex_unlock(&adev->lock);
3829 pthread_mutex_unlock(&out->lock);
3830 ret = -ENOSYS;
3831 goto routing_fail;
3832 }
3833
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003834 /*
3835 * select_devices() call below switches all the usecases on the same
3836 * backend to the new device. Refer to check_usecases_codec_backend() in
3837 * the select_devices(). But how do we undo this?
3838 *
3839 * For example, music playback is active on headset (deep-buffer usecase)
3840 * and if we go to ringtones and select a ringtone, low-latency usecase
3841 * will be started on headset+speaker. As we can't enable headset+speaker
3842 * and headset devices at the same time, select_devices() switches the music
3843 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3844 * So when the ringtone playback is completed, how do we undo the same?
3845 *
3846 * We are relying on the out_set_parameters() call on deep-buffer output,
3847 * once the ringtone playback is ended.
3848 * NOTE: We should not check if the current devices are same as new devices.
3849 * Because select_devices() must be called to switch back the music
3850 * playback to headset.
3851 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003852 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003853 audio_devices_t new_dev = val;
3854 bool same_dev = out->devices == new_dev;
3855 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003856
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003857 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08003858 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003859 if (adev->mode == AUDIO_MODE_IN_CALL) {
3860 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003861 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3862 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
3863 audio_extn_usb_set_service_interval(true /*playback*/,
3864 service_interval,
3865 &reconfig);
3866 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
3867 }
3868 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003869 }
3870 } else {
3871 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003872 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003873 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003874 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003875
3876 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003877 if (!same_dev) {
3878 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303879 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3880 adev->perf_lock_opts,
3881 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003882 if (adev->adm_on_routing_change)
3883 adev->adm_on_routing_change(adev->adm_data,
3884 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003885 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303886 if (!bypass_a2dp) {
3887 select_devices(adev, out->usecase);
3888 } else {
3889 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3890 select_devices(adev, out->usecase);
3891 out->devices = new_dev;
3892 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003893
3894 if (!same_dev) {
3895 // on device switch force swap, lower functions will make sure
3896 // to check if swap is allowed or not.
3897 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05303898 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003899 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303900 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3901 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003902 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303903 pthread_mutex_lock(&out->compr_mute_lock);
3904 out->a2dp_compress_mute = false;
3905 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3906 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08003907 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
3908 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303909 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003910 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003911 }
3912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003914 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003916 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003917
3918 if (out == adev->primary_output) {
3919 pthread_mutex_lock(&adev->lock);
3920 audio_extn_set_parameters(adev, parms);
3921 pthread_mutex_unlock(&adev->lock);
3922 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003923 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003924 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003925 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003926
3927 audio_extn_dts_create_state_notifier_node(out->usecase);
3928 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3929 popcount(out->channel_mask),
3930 out->playback_started);
3931
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003932 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003933 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003934
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303935 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3936 if (err >= 0) {
3937 strlcpy(out->profile, value, sizeof(out->profile));
3938 ALOGV("updating stream profile with value '%s'", out->profile);
3939 lock_output_stream(out);
3940 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3941 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07003942 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303943 out->sample_rate, out->bit_width,
3944 out->channel_mask, out->profile,
3945 &out->app_type_cfg);
3946 pthread_mutex_unlock(&out->lock);
3947 }
3948
Alexy Joseph98988832017-01-13 14:56:59 -08003949 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08003950 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
3951 // and vendor.audio.hal.output.suspend.supported is set to true
3952 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08003953 //check suspend parameter only for low latency and if the property
3954 //is enabled
3955 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3956 ALOGI("%s: got suspend_playback %s", __func__, value);
3957 lock_output_stream(out);
3958 if (!strncmp(value, "false", 5)) {
3959 //suspend_playback=false is supposed to set QOS value back to 75%
3960 //the mixer control sent with value Enable will achieve that
3961 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3962 } else if (!strncmp (value, "true", 4)) {
3963 //suspend_playback=true is supposed to remove QOS value
3964 //resetting the mixer control will set the default value
3965 //for the mixer control which is Disable and this removes the QOS vote
3966 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3967 } else {
3968 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3969 " got %s", __func__, value);
3970 ret = -1;
3971 }
3972
3973 if (ret != 0) {
3974 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3975 __func__, out->pm_qos_mixer_path, ret);
3976 }
3977
3978 pthread_mutex_unlock(&out->lock);
3979 }
3980 }
3981 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303983error:
Eric Laurent994a6932013-07-17 11:51:42 -07003984 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003985 return ret;
3986}
3987
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003988static bool stream_get_parameter_channels(struct str_parms *query,
3989 struct str_parms *reply,
3990 audio_channel_mask_t *supported_channel_masks) {
3991 int ret = -1;
3992 char value[512];
3993 bool first = true;
3994 size_t i, j;
3995
3996 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3997 ret = 0;
3998 value[0] = '\0';
3999 i = 0;
4000 while (supported_channel_masks[i] != 0) {
4001 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4002 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4003 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304004 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004005
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304006 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004007 first = false;
4008 break;
4009 }
4010 }
4011 i++;
4012 }
4013 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4014 }
4015 return ret == 0;
4016}
4017
4018static bool stream_get_parameter_formats(struct str_parms *query,
4019 struct str_parms *reply,
4020 audio_format_t *supported_formats) {
4021 int ret = -1;
4022 char value[256];
4023 size_t i, j;
4024 bool first = true;
4025
4026 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4027 ret = 0;
4028 value[0] = '\0';
4029 i = 0;
4030 while (supported_formats[i] != 0) {
4031 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4032 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4033 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304034 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004035 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304036 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004037 first = false;
4038 break;
4039 }
4040 }
4041 i++;
4042 }
4043 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4044 }
4045 return ret == 0;
4046}
4047
4048static bool stream_get_parameter_rates(struct str_parms *query,
4049 struct str_parms *reply,
4050 uint32_t *supported_sample_rates) {
4051
4052 int i;
4053 char value[256];
4054 int ret = -1;
4055 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4056 ret = 0;
4057 value[0] = '\0';
4058 i=0;
4059 int cursor = 0;
4060 while (supported_sample_rates[i]) {
4061 int avail = sizeof(value) - cursor;
4062 ret = snprintf(value + cursor, avail, "%s%d",
4063 cursor > 0 ? "|" : "",
4064 supported_sample_rates[i]);
4065 if (ret < 0 || ret >= avail) {
4066 // if cursor is at the last element of the array
4067 // overwrite with \0 is duplicate work as
4068 // snprintf already put a \0 in place.
4069 // else
4070 // we had space to write the '|' at value[cursor]
4071 // (which will be overwritten) or no space to fill
4072 // the first element (=> cursor == 0)
4073 value[cursor] = '\0';
4074 break;
4075 }
4076 cursor += ret;
4077 ++i;
4078 }
4079 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4080 value);
4081 }
4082 return ret >= 0;
4083}
4084
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4086{
4087 struct stream_out *out = (struct stream_out *)stream;
4088 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004089 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004090 char value[256];
4091 struct str_parms *reply = str_parms_create();
4092 size_t i, j;
4093 int ret;
4094 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004095
4096 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004097 if (reply) {
4098 str_parms_destroy(reply);
4099 }
4100 if (query) {
4101 str_parms_destroy(query);
4102 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004103 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4104 return NULL;
4105 }
4106
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004107 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004108 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4109 if (ret >= 0) {
4110 value[0] = '\0';
4111 i = 0;
4112 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004113 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4114 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004115 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004116 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004117 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004118 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004119 first = false;
4120 break;
4121 }
4122 }
4123 i++;
4124 }
4125 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4126 str = str_parms_to_str(reply);
4127 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004128 voice_extn_out_get_parameters(out, query, reply);
4129 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004131
Alexy Joseph62142aa2015-11-16 15:10:34 -08004132
4133 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4134 if (ret >= 0) {
4135 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304136 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4137 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004138 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304139 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004140 } else {
4141 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304142 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004143 }
4144 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004145 if (str)
4146 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004147 str = str_parms_to_str(reply);
4148 }
4149
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004150 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4151 if (ret >= 0) {
4152 value[0] = '\0';
4153 i = 0;
4154 first = true;
4155 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004156 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4157 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004158 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004159 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004160 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004161 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004162 first = false;
4163 break;
4164 }
4165 }
4166 i++;
4167 }
4168 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004169 if (str)
4170 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004171 str = str_parms_to_str(reply);
4172 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004173
4174 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4175 if (ret >= 0) {
4176 value[0] = '\0';
4177 i = 0;
4178 first = true;
4179 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004180 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4181 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004182 if (!first) {
4183 strlcat(value, "|", sizeof(value));
4184 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004185 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004186 first = false;
4187 break;
4188 }
4189 }
4190 i++;
4191 }
4192 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4193 if (str)
4194 free(str);
4195 str = str_parms_to_str(reply);
4196 }
4197
Alexy Joseph98988832017-01-13 14:56:59 -08004198 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4199 //only low latency track supports suspend_resume
4200 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004201 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004202 if (str)
4203 free(str);
4204 str = str_parms_to_str(reply);
4205 }
4206
4207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004208 str_parms_destroy(query);
4209 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004210 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004211 return str;
4212}
4213
4214static uint32_t out_get_latency(const struct audio_stream_out *stream)
4215{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004216 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004217 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004218 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004219
Alexy Josephaa54c872014-12-03 02:46:47 -08004220 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304221 lock_output_stream(out);
4222 latency = audio_extn_utils_compress_get_dsp_latency(out);
4223 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004224 } else if ((out->realtime) ||
4225 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004226 // since the buffer won't be filled up faster than realtime,
4227 // return a smaller number
4228 if (out->config.rate)
4229 period_ms = (out->af_period_multiplier * out->config.period_size *
4230 1000) / (out->config.rate);
4231 else
4232 period_ms = 0;
4233 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004234 } else {
4235 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004236 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004237 }
4238
yidongh0515e042017-07-06 15:00:34 +08004239 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004240 latency += audio_extn_a2dp_get_encoder_latency();
4241
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304242 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004243 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004244}
4245
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304246static float AmpToDb(float amplification)
4247{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304248 float db = DSD_VOLUME_MIN_DB;
4249 if (amplification > 0) {
4250 db = 20 * log10(amplification);
4251 if(db < DSD_VOLUME_MIN_DB)
4252 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304253 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304254 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304255}
4256
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304257static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4258 float right)
4259{
4260 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304261 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304262 char mixer_ctl_name[128];
4263 struct audio_device *adev = out->dev;
4264 struct mixer_ctl *ctl;
4265 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4266 PCM_PLAYBACK);
4267
4268 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4269 "Compress Playback %d Volume", pcm_device_id);
4270 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4271 if (!ctl) {
4272 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4273 __func__, mixer_ctl_name);
4274 return -EINVAL;
4275 }
4276 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4277 __func__, mixer_ctl_name, left, right);
4278 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4279 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4280 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4281
4282 return 0;
4283}
4284
Zhou Song2b8f28f2017-09-11 10:51:38 +08004285static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4286 float right)
4287{
4288 struct stream_out *out = (struct stream_out *)stream;
4289 char mixer_ctl_name[] = "App Type Gain";
4290 struct audio_device *adev = out->dev;
4291 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304292 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004293
4294 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4295 if (!ctl) {
4296 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4297 __func__, mixer_ctl_name);
4298 return -EINVAL;
4299 }
4300
4301 set_values[0] = 0; //0: Rx Session 1:Tx Session
4302 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304303 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4304 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004305
4306 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4307 return 0;
4308}
4309
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310static int out_set_volume(struct audio_stream_out *stream, float left,
4311 float right)
4312{
Eric Laurenta9024de2013-04-04 09:19:12 -07004313 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004314 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304315 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004316
Eric Laurenta9024de2013-04-04 09:19:12 -07004317 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4318 /* only take left channel into account: the API is for stereo anyway */
4319 out->muted = (left == 0.0f);
4320 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004321 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304322 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004323 /*
4324 * Set mute or umute on HDMI passthrough stream.
4325 * Only take left channel into account.
4326 * Mute is 0 and unmute 1
4327 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304328 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304329 } else if (out->format == AUDIO_FORMAT_DSD){
4330 char mixer_ctl_name[128] = "DSD Volume";
4331 struct audio_device *adev = out->dev;
4332 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4333
4334 if (!ctl) {
4335 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4336 __func__, mixer_ctl_name);
4337 return -EINVAL;
4338 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304339 volume[0] = (long)(AmpToDb(left));
4340 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304341 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4342 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004343 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304344 pthread_mutex_lock(&out->compr_mute_lock);
4345 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
4346 if (!out->a2dp_compress_mute)
4347 ret = out_set_compr_volume(stream, left, right);
4348 out->volume_l = left;
4349 out->volume_r = right;
4350 pthread_mutex_unlock(&out->compr_mute_lock);
4351 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004352 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004353 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004354 if (!out->standby)
4355 ret = out_set_voip_volume(stream, left, right);
4356 out->volume_l = left;
4357 out->volume_r = right;
4358 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004359 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004360
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004361 return -ENOSYS;
4362}
4363
Zhou Songc9672822017-08-16 16:01:39 +08004364static void update_frames_written(struct stream_out *out, size_t bytes)
4365{
4366 size_t bpf = 0;
4367
4368 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4369 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4370 bpf = 1;
4371 else if (!is_offload_usecase(out->usecase))
4372 bpf = audio_bytes_per_sample(out->format) *
4373 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004374
4375 pthread_mutex_lock(&out->position_query_lock);
4376 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004377 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004378 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4379 }
4380 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004381}
4382
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004383static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4384 size_t bytes)
4385{
4386 struct stream_out *out = (struct stream_out *)stream;
4387 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004388 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304389 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004390 const size_t frame_size = audio_stream_out_frame_size(stream);
4391 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004392
Haynes Mathew George380745d2017-10-04 15:27:45 -07004393 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004394 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304395
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304396 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004397
Dhananjay Kumarac341582017-02-23 23:42:25 +05304398 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304399 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304400 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4401 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004402 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304403 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304404 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304405 ALOGD(" %s: sound card is not active/SSR state", __func__);
4406 ret= -EIO;
4407 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304408 }
4409 }
4410
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304411 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304412 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304413 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304414 goto exit;
4415 }
4416
Haynes Mathew George16081042017-05-31 17:16:49 -07004417 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4418 ret = -EINVAL;
4419 goto exit;
4420 }
4421
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304422 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4423 !out->is_iec61937_info_available) {
4424
4425 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4426 out->is_iec61937_info_available = true;
4427 } else if (audio_extn_passthru_is_enabled()) {
4428 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304429 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304430
4431 if((out->format == AUDIO_FORMAT_DTS) ||
4432 (out->format == AUDIO_FORMAT_DTS_HD)) {
4433 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4434 buffer, bytes);
4435 if (ret) {
4436 if (ret != -ENOSYS) {
4437 out->is_iec61937_info_available = false;
4438 ALOGD("iec61937 transmission info not yet updated retry");
4439 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304440 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304441 /* if stream has started and after that there is
4442 * stream config change (iec transmission config)
4443 * then trigger select_device to update backend configuration.
4444 */
4445 out->stream_config_changed = true;
4446 pthread_mutex_lock(&adev->lock);
4447 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304448 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4449 ret = -EINVAL;
4450 goto exit;
4451 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304452 pthread_mutex_unlock(&adev->lock);
4453 out->stream_config_changed = false;
4454 out->is_iec61937_info_available = true;
4455 }
4456 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304457
Garmond Leung317cbf12017-09-13 16:20:50 -07004458 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304459 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4460 (out->is_iec61937_info_available == true)) {
4461 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4462 ret = -EINVAL;
4463 goto exit;
4464 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304465 }
4466 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304467
4468 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4469 (audio_extn_a2dp_is_suspended())) {
4470 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4471 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304472 ret = -EIO;
4473 goto exit;
4474 }
4475 }
4476 }
4477
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004478 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004479 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004480 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004481 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4482 ret = voice_extn_compress_voip_start_output_stream(out);
4483 else
4484 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004485 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004486 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004487 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004488 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004489 goto exit;
4490 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304491 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004492 if (last_known_cal_step != -1) {
4493 ALOGD("%s: retry previous failed cal level set", __func__);
4494 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304495 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004496 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304497
4498 if ((out->is_iec61937_info_available == true) &&
4499 (audio_extn_passthru_is_passthrough_stream(out))&&
4500 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4501 ret = -EINVAL;
4502 goto exit;
4503 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004504 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004505
Ashish Jain81eb2a82015-05-13 10:52:34 +05304506 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004507 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304508 adev->is_channel_status_set = true;
4509 }
4510
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004511 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004512 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004513 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004514 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004515 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4516 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304517 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4518 ALOGD("copl(%p):send next track params in gapless", out);
4519 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4520 out->send_next_track_params = false;
4521 out->is_compr_metadata_avail = false;
4522 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004523 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304524 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304525 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004526
Ashish Jain83a6cc22016-06-28 14:34:17 +05304527 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304528 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304529 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304530 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004531 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304532 return -EINVAL;
4533 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304534 audio_format_t dst_format = out->hal_op_format;
4535 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304536
4537 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4538 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4539
Ashish Jain83a6cc22016-06-28 14:34:17 +05304540 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304541 dst_format,
4542 buffer,
4543 src_format,
4544 frames);
4545
Ashish Jain83a6cc22016-06-28 14:34:17 +05304546 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304547 bytes_to_write);
4548
4549 /*Convert written bytes in audio flinger format*/
4550 if (ret > 0)
4551 ret = ((ret * format_to_bitwidth_table[out->format]) /
4552 format_to_bitwidth_table[dst_format]);
4553 }
4554 } else
4555 ret = compress_write(out->compr, buffer, bytes);
4556
Zhou Songc9672822017-08-16 16:01:39 +08004557 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4558 update_frames_written(out, bytes);
4559
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304560 if (ret < 0)
4561 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08004562 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304563 /*msg to cb thread only if non blocking write is enabled*/
4564 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304565 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004566 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304567 } else if (-ENETRESET == ret) {
4568 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304569 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304570 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304571 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004572 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304573 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004574 }
Ashish Jain5106d362016-05-11 19:23:33 +05304575
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304576 /* Call compr start only when non-zero bytes of data is there to be rendered */
4577 if (!out->playback_started && ret > 0) {
4578 int status = compress_start(out->compr);
4579 if (status < 0) {
4580 ret = status;
4581 ALOGE("%s: compr start failed with err %d", __func__, errno);
4582 goto exit;
4583 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004584 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004585 out->playback_started = 1;
4586 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004587
4588 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4589 popcount(out->channel_mask),
4590 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004591 }
4592 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004593 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004594 return ret;
4595 } else {
4596 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004597 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004598 if (out->muted)
4599 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004600 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
4601 __func__, frames, frame_size, bytes_to_write);
4602
4603 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
4604 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4605 int16_t *src = (int16_t *)buffer;
4606 int16_t *dst = (int16_t *)buffer;
4607
4608 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
4609 out->format != AUDIO_FORMAT_PCM_16_BIT,
4610 "out_write called for incall music use case with wrong properties");
4611
4612 /*
4613 * FIXME: this can be removed once audio flinger mixer supports
4614 * mono output
4615 */
4616
4617 /*
4618 * Code below goes over each frame in the buffer and adds both
4619 * L and R samples and then divides by 2 to convert to mono
4620 */
4621 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
4622 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
4623 }
4624 bytes_to_write /= 2;
4625 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004626
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304627 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004628
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004629 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004630
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004631 if (out->config.rate)
4632 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4633 out->config.rate;
4634
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004635 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004636 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4637
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004638 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004639 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004640 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304641 out->convert_buffer != NULL) {
4642
4643 memcpy_by_audio_format(out->convert_buffer,
4644 out->hal_op_format,
4645 buffer,
4646 out->hal_ip_format,
4647 out->config.period_size * out->config.channels);
4648
4649 ret = pcm_write(out->pcm, out->convert_buffer,
4650 (out->config.period_size *
4651 out->config.channels *
4652 format_to_bitwidth_table[out->hal_op_format]));
4653 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304654 /*
4655 * To avoid underrun in DSP when the application is not pumping
4656 * data at required rate, check for the no. of bytes and ignore
4657 * pcm_write if it is less than actual buffer size.
4658 * It is a work around to a change in compress VOIP driver.
4659 */
4660 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4661 bytes < (out->config.period_size * out->config.channels *
4662 audio_bytes_per_sample(out->format))) {
4663 size_t voip_buf_size =
4664 out->config.period_size * out->config.channels *
4665 audio_bytes_per_sample(out->format);
4666 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4667 __func__, bytes, voip_buf_size);
4668 usleep(((uint64_t)voip_buf_size - bytes) *
4669 1000000 / audio_stream_out_frame_size(stream) /
4670 out_get_sample_rate(&out->stream.common));
4671 ret = 0;
4672 } else
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004673 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304674 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004675
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004676 release_out_focus(out);
4677
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304678 if (ret < 0)
4679 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004680 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304681 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004682 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004683 }
4684
4685exit:
Zhou Songc9672822017-08-16 16:01:39 +08004686 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304687 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304688 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304689 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004690 pthread_mutex_unlock(&out->lock);
4691
4692 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004693 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004694 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304695 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304696 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304697 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304698 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304699 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304700 out->standby = true;
4701 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304702 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304703 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4704 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4705 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004706
4707 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05304708 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004709 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004710 return ret;
4711 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004712 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004713 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004714 return bytes;
4715}
4716
4717static int out_get_render_position(const struct audio_stream_out *stream,
4718 uint32_t *dsp_frames)
4719{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004720 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004721
4722 if (dsp_frames == NULL)
4723 return -EINVAL;
4724
4725 *dsp_frames = 0;
4726 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004727 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304728
4729 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4730 * this operation and adev_close_output_stream(where out gets reset).
4731 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304732 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004733 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05304734 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004735 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304736 return 0;
4737 }
4738
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004739 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304740 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304741 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004742 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304743 if (ret < 0)
4744 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004745 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304746 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004747 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304748 if (-ENETRESET == ret) {
4749 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304750 out->card_status = CARD_STATUS_OFFLINE;
4751 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304752 } else if(ret < 0) {
4753 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304754 ret = -EINVAL;
4755 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304756 /*
4757 * Handle corner case where compress session is closed during SSR
4758 * and timestamp is queried
4759 */
4760 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304761 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304762 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304763 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004764 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05304765 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304766 pthread_mutex_unlock(&out->lock);
4767 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004768 } else if (audio_is_linear_pcm(out->format)) {
4769 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004770 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08004771 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004772 } else
4773 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004774}
4775
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004776static int out_add_audio_effect(const struct audio_stream *stream __unused,
4777 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004778{
4779 return 0;
4780}
4781
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004782static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4783 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004784{
4785 return 0;
4786}
4787
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004788static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4789 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004790{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304791 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004792}
4793
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004794static int out_get_presentation_position(const struct audio_stream_out *stream,
4795 uint64_t *frames, struct timespec *timestamp)
4796{
4797 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05304798 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07004799 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004800
Ashish Jain5106d362016-05-11 19:23:33 +05304801 /* below piece of code is not guarded against any lock because audioFliner serializes
4802 * this operation and adev_close_output_stream( where out gets reset).
4803 */
4804 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304805 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004806 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05304807 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4808 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4809 return 0;
4810 }
4811
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004812 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004813
Ashish Jain5106d362016-05-11 19:23:33 +05304814 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4815 ret = compress_get_tstamp(out->compr, &dsp_frames,
4816 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004817 // Adjustment accounts for A2dp encoder latency with offload usecases
4818 // Note: Encoder latency is returned in ms.
4819 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4820 unsigned long offset =
4821 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4822 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4823 }
Ashish Jain5106d362016-05-11 19:23:33 +05304824 ALOGVV("%s rendered frames %ld sample_rate %d",
4825 __func__, dsp_frames, out->sample_rate);
4826 *frames = dsp_frames;
4827 if (ret < 0)
4828 ret = -errno;
4829 if (-ENETRESET == ret) {
4830 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304831 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304832 ret = -EINVAL;
4833 } else
4834 ret = 0;
4835 /* this is the best we can do */
4836 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07004837 } else {
4838 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08004839 unsigned int avail;
4840 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
4841 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
4842 int64_t signed_frames = out->written - kernel_buffer_size + avail;
4843 // This adjustment accounts for buffering after app processor.
4844 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07004845 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08004846 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07004847
Weiyin Jiangd4633762018-03-16 12:05:03 +08004848 // Adjustment accounts for A2dp encoder latency with non offload usecases
4849 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
4850 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4851 signed_frames -=
4852 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4853 }
4854
4855 // It would be unusual for this value to be negative, but check just in case ...
4856 if (signed_frames >= 0) {
4857 *frames = signed_frames;
4858 ret = 0;
4859 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004860 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304861 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304862 *frames = out->written;
4863 clock_gettime(CLOCK_MONOTONIC, timestamp);
4864 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004865 }
4866 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004867 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004868 return ret;
4869}
4870
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004871static int out_set_callback(struct audio_stream_out *stream,
4872 stream_callback_t callback, void *cookie)
4873{
4874 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004875 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004876
4877 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004878 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004879 out->client_callback = callback;
4880 out->client_cookie = cookie;
4881 if (out->adsp_hdlr_stream_handle) {
4882 ret = audio_extn_adsp_hdlr_stream_set_callback(
4883 out->adsp_hdlr_stream_handle,
4884 callback,
4885 cookie);
4886 if (ret)
4887 ALOGW("%s:adsp hdlr callback registration failed %d",
4888 __func__, ret);
4889 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004890 pthread_mutex_unlock(&out->lock);
4891 return 0;
4892}
4893
4894static int out_pause(struct audio_stream_out* stream)
4895{
4896 struct stream_out *out = (struct stream_out *)stream;
4897 int status = -ENOSYS;
4898 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004899 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004900 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004901 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004902 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304903 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304904 status = compress_pause(out->compr);
4905
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004906 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004907
Mingming Yin21854652016-04-13 11:54:02 -07004908 if (audio_extn_passthru_is_active()) {
4909 ALOGV("offload use case, pause passthru");
4910 audio_extn_passthru_on_pause(out);
4911 }
4912
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304913 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004914 audio_extn_dts_notify_playback_state(out->usecase, 0,
4915 out->sample_rate, popcount(out->channel_mask),
4916 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004917 }
4918 pthread_mutex_unlock(&out->lock);
4919 }
4920 return status;
4921}
4922
4923static int out_resume(struct audio_stream_out* stream)
4924{
4925 struct stream_out *out = (struct stream_out *)stream;
4926 int status = -ENOSYS;
4927 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004928 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004929 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004930 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004931 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004932 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304933 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304934 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004935 }
4936 if (!status) {
4937 out->offload_state = OFFLOAD_STATE_PLAYING;
4938 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304939 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004940 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4941 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004942 }
4943 pthread_mutex_unlock(&out->lock);
4944 }
4945 return status;
4946}
4947
4948static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
4949{
4950 struct stream_out *out = (struct stream_out *)stream;
4951 int status = -ENOSYS;
4952 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004953 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004954 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004955 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
4956 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
4957 else
4958 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
4959 pthread_mutex_unlock(&out->lock);
4960 }
4961 return status;
4962}
4963
4964static int out_flush(struct audio_stream_out* stream)
4965{
4966 struct stream_out *out = (struct stream_out *)stream;
4967 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004968 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004969 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004970 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004971 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
4972 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004973 } else {
4974 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
4975 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08004976 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004977 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004978 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004979 return 0;
4980 }
4981 return -ENOSYS;
4982}
4983
Haynes Mathew George16081042017-05-31 17:16:49 -07004984static int out_stop(const struct audio_stream_out* stream)
4985{
4986 struct stream_out *out = (struct stream_out *)stream;
4987 struct audio_device *adev = out->dev;
4988 int ret = -ENOSYS;
4989
4990 ALOGV("%s", __func__);
4991 pthread_mutex_lock(&adev->lock);
4992 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4993 out->playback_started && out->pcm != NULL) {
4994 pcm_stop(out->pcm);
4995 ret = stop_output_stream(out);
4996 out->playback_started = false;
4997 }
4998 pthread_mutex_unlock(&adev->lock);
4999 return ret;
5000}
5001
5002static int out_start(const struct audio_stream_out* stream)
5003{
5004 struct stream_out *out = (struct stream_out *)stream;
5005 struct audio_device *adev = out->dev;
5006 int ret = -ENOSYS;
5007
5008 ALOGV("%s", __func__);
5009 pthread_mutex_lock(&adev->lock);
5010 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5011 !out->playback_started && out->pcm != NULL) {
5012 ret = start_output_stream(out);
5013 if (ret == 0) {
5014 out->playback_started = true;
5015 }
5016 }
5017 pthread_mutex_unlock(&adev->lock);
5018 return ret;
5019}
5020
5021/*
5022 * Modify config->period_count based on min_size_frames
5023 */
5024static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5025{
5026 int periodCountRequested = (min_size_frames + config->period_size - 1)
5027 / config->period_size;
5028 int periodCount = MMAP_PERIOD_COUNT_MIN;
5029
5030 ALOGV("%s original config.period_size = %d config.period_count = %d",
5031 __func__, config->period_size, config->period_count);
5032
5033 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5034 periodCount *= 2;
5035 }
5036 config->period_count = periodCount;
5037
5038 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5039}
5040
5041static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5042 int32_t min_size_frames,
5043 struct audio_mmap_buffer_info *info)
5044{
5045 struct stream_out *out = (struct stream_out *)stream;
5046 struct audio_device *adev = out->dev;
5047 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005048 unsigned int offset1 = 0;
5049 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005050 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005051 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005052
5053 ALOGV("%s", __func__);
5054 pthread_mutex_lock(&adev->lock);
5055
5056 if (info == NULL || min_size_frames == 0) {
5057 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5058 ret = -EINVAL;
5059 goto exit;
5060 }
5061 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5062 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5063 ret = -ENOSYS;
5064 goto exit;
5065 }
5066 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5067 if (out->pcm_device_id < 0) {
5068 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5069 __func__, out->pcm_device_id, out->usecase);
5070 ret = -EINVAL;
5071 goto exit;
5072 }
5073
5074 adjust_mmap_period_count(&out->config, min_size_frames);
5075
5076 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5077 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5078 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5079 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
5080 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5081 step = "open";
5082 ret = -ENODEV;
5083 goto exit;
5084 }
5085 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5086 if (ret < 0) {
5087 step = "begin";
5088 goto exit;
5089 }
5090 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
5091 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005092 ret = platform_get_mmap_data_fd(adev->platform,
5093 out->pcm_device_id, 0 /*playback*/,
5094 &info->shared_memory_fd,
5095 &mmap_size);
5096 if (ret < 0) {
5097 step = "get_mmap_fd";
5098 goto exit;
5099 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005100 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005101 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005102
5103 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5104 if (ret < 0) {
5105 step = "commit";
5106 goto exit;
5107 }
5108
5109 out->standby = false;
5110 ret = 0;
5111
5112 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5113 __func__, info->shared_memory_address, info->buffer_size_frames);
5114
5115exit:
5116 if (ret != 0) {
5117 if (out->pcm == NULL) {
5118 ALOGE("%s: %s - %d", __func__, step, ret);
5119 } else {
5120 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5121 pcm_close(out->pcm);
5122 out->pcm = NULL;
5123 }
5124 }
5125 pthread_mutex_unlock(&adev->lock);
5126 return ret;
5127}
5128
5129static int out_get_mmap_position(const struct audio_stream_out *stream,
5130 struct audio_mmap_position *position)
5131{
5132 struct stream_out *out = (struct stream_out *)stream;
5133 ALOGVV("%s", __func__);
5134 if (position == NULL) {
5135 return -EINVAL;
5136 }
5137 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005138 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005139 return -ENOSYS;
5140 }
5141 if (out->pcm == NULL) {
5142 return -ENOSYS;
5143 }
5144
5145 struct timespec ts = { 0, 0 };
5146 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5147 if (ret < 0) {
5148 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5149 return ret;
5150 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005151 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005152 return 0;
5153}
5154
5155
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005156/** audio_stream_in implementation **/
5157static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5158{
5159 struct stream_in *in = (struct stream_in *)stream;
5160
5161 return in->config.rate;
5162}
5163
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005164static int in_set_sample_rate(struct audio_stream *stream __unused,
5165 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005166{
5167 return -ENOSYS;
5168}
5169
5170static size_t in_get_buffer_size(const struct audio_stream *stream)
5171{
5172 struct stream_in *in = (struct stream_in *)stream;
5173
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005174 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5175 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005176 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5177 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 -07005178 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5179 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305180 else if(audio_extn_cin_attached_usecase(in->usecase))
5181 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005182
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005183 return in->config.period_size * in->af_period_multiplier *
5184 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005185}
5186
5187static uint32_t in_get_channels(const struct audio_stream *stream)
5188{
5189 struct stream_in *in = (struct stream_in *)stream;
5190
5191 return in->channel_mask;
5192}
5193
5194static audio_format_t in_get_format(const struct audio_stream *stream)
5195{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005196 struct stream_in *in = (struct stream_in *)stream;
5197
5198 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005199}
5200
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005201static int in_set_format(struct audio_stream *stream __unused,
5202 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005203{
5204 return -ENOSYS;
5205}
5206
5207static int in_standby(struct audio_stream *stream)
5208{
5209 struct stream_in *in = (struct stream_in *)stream;
5210 struct audio_device *adev = in->dev;
5211 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305212 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5213 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005214 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305215
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005216 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005217 if (!in->standby && in->is_st_session) {
5218 ALOGD("%s: sound trigger pcm stop lab", __func__);
5219 audio_extn_sound_trigger_stop_lab(in);
5220 in->standby = 1;
5221 }
5222
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005223 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005224 if (adev->adm_deregister_stream)
5225 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5226
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005227 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005228 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005229 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005230 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005231 voice_extn_compress_voip_close_input_stream(stream);
5232 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005233 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5234 do_stop = in->capture_started;
5235 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005236 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305237 if (audio_extn_cin_attached_usecase(in->usecase))
5238 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005239 }
5240
5241 if (do_stop) {
Zhou Songa8895042016-07-05 17:54:22 +08005242 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005243 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005244 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005245 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005246 in->pcm = NULL;
5247 }
5248 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005249 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08005250 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005251 }
5252 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005253 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005254 return status;
5255}
5256
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005257static int in_dump(const struct audio_stream *stream __unused,
5258 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005259{
5260 return 0;
5261}
5262
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305263static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5264{
5265 if (!stream || !parms)
5266 return;
5267
5268 struct stream_in *in = (struct stream_in *)stream;
5269 struct audio_device *adev = in->dev;
5270
5271 card_status_t status;
5272 int card;
5273 if (parse_snd_card_status(parms, &card, &status) < 0)
5274 return;
5275
5276 pthread_mutex_lock(&adev->lock);
5277 bool valid_cb = (card == adev->snd_card);
5278 pthread_mutex_unlock(&adev->lock);
5279
5280 if (!valid_cb)
5281 return;
5282
5283 lock_input_stream(in);
5284 if (in->card_status != status)
5285 in->card_status = status;
5286 pthread_mutex_unlock(&in->lock);
5287
5288 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5289 use_case_table[in->usecase],
5290 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5291
5292 // a better solution would be to report error back to AF and let
5293 // it put the stream to standby
5294 if (status == CARD_STATUS_OFFLINE)
5295 in_standby(&in->stream.common);
5296
5297 return;
5298}
5299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005300static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5301{
5302 struct stream_in *in = (struct stream_in *)stream;
5303 struct audio_device *adev = in->dev;
5304 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005305 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005306 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005307
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305308 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005309 parms = str_parms_create_str(kvpairs);
5310
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305311 if (!parms)
5312 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005313 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005314 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005315
5316 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5317 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005318 val = atoi(value);
5319 /* no audio source uses val == 0 */
5320 if ((in->source != val) && (val != 0)) {
5321 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005322 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5323 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5324 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005325 (in->config.rate == 8000 || in->config.rate == 16000 ||
5326 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005327 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005328 err = voice_extn_compress_voip_open_input_stream(in);
5329 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005330 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005331 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005332 }
5333 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005334 }
5335 }
5336
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005337 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5338 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005339 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005340 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5341
5342 // Workaround: If routing to an non existing usb device, fail gracefully
5343 // The routing request will otherwise block during 10 second
5344 int card;
5345 if (audio_is_usb_in_device(val) &&
5346 (card = get_alive_usb_card(parms)) >= 0) {
5347
5348 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5349 ret = -ENOSYS;
5350 } else {
5351
5352 in->device = val;
5353 /* If recording is in progress, change the tx device to new device */
5354 if (!in->standby && !in->is_st_session) {
5355 ALOGV("update input routing change");
5356 // inform adm before actual routing to prevent glitches.
5357 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005358 adev->adm_on_routing_change(adev->adm_data,
5359 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005360 ret = select_devices(adev, in->usecase);
5361 }
5362 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005363 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005364 }
5365 }
5366
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305367 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5368 if (err >= 0) {
5369 strlcpy(in->profile, value, sizeof(in->profile));
5370 ALOGV("updating stream profile with value '%s'", in->profile);
5371 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5372 &adev->streams_input_cfg_list,
5373 in->device, in->flags, in->format,
5374 in->sample_rate, in->bit_width,
5375 in->profile, &in->app_type_cfg);
5376 }
5377
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005378 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005379 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005380
5381 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305382error:
Eric Laurent994a6932013-07-17 11:51:42 -07005383 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005384 return ret;
5385}
5386
5387static char* in_get_parameters(const struct audio_stream *stream,
5388 const char *keys)
5389{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005390 struct stream_in *in = (struct stream_in *)stream;
5391 struct str_parms *query = str_parms_create_str(keys);
5392 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005393 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005394
5395 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005396 if (reply) {
5397 str_parms_destroy(reply);
5398 }
5399 if (query) {
5400 str_parms_destroy(query);
5401 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005402 ALOGE("in_get_parameters: failed to create query or reply");
5403 return NULL;
5404 }
5405
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005406 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005407
5408 voice_extn_in_get_parameters(in, query, reply);
5409
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005410 stream_get_parameter_channels(query, reply,
5411 &in->supported_channel_masks[0]);
5412 stream_get_parameter_formats(query, reply,
5413 &in->supported_formats[0]);
5414 stream_get_parameter_rates(query, reply,
5415 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005416 str = str_parms_to_str(reply);
5417 str_parms_destroy(query);
5418 str_parms_destroy(reply);
5419
5420 ALOGV("%s: exit: returns - %s", __func__, str);
5421 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005422}
5423
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005424static int in_set_gain(struct audio_stream_in *stream __unused,
5425 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005426{
5427 return 0;
5428}
5429
5430static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5431 size_t bytes)
5432{
5433 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305434
5435 if (in == NULL) {
5436 ALOGE("%s: stream_in ptr is NULL", __func__);
5437 return -EINVAL;
5438 }
5439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005440 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305441 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305442 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005443
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005444 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305445
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005446 if (in->is_st_session) {
5447 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5448 /* Read from sound trigger HAL */
5449 audio_extn_sound_trigger_read(in, buffer, bytes);
5450 pthread_mutex_unlock(&in->lock);
5451 return bytes;
5452 }
5453
Haynes Mathew George16081042017-05-31 17:16:49 -07005454 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5455 ret = -ENOSYS;
5456 goto exit;
5457 }
5458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005459 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005460 pthread_mutex_lock(&adev->lock);
5461 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5462 ret = voice_extn_compress_voip_start_input_stream(in);
5463 else
5464 ret = start_input_stream(in);
5465 pthread_mutex_unlock(&adev->lock);
5466 if (ret != 0) {
5467 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005468 }
5469 in->standby = 0;
5470 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005471
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005472 // what's the duration requested by the client?
5473 long ns = 0;
5474
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305475 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005476 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5477 in->config.rate;
5478
5479 request_in_focus(in, ns);
5480 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005481
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305482 if (audio_extn_cin_attached_usecase(in->usecase)) {
5483 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5484 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305485 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005486 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305487 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005488 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005489 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005490 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005491 } else if (audio_extn_ffv_get_stream() == in) {
5492 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305493 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005494 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305495 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5496 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5497 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5498 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305499 ret = -EINVAL;
5500 goto exit;
5501 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305502 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305503 ret = -errno;
5504 }
5505 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305506 /* bytes read is always set to bytes for non compress usecases */
5507 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005508 }
5509
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005510 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005511
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005512 /*
5513 * Instead of writing zeroes here, we could trust the hardware
5514 * to always provide zeroes when muted.
5515 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305516 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5517 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005518 memset(buffer, 0, bytes);
5519
5520exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005521 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305522 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005523 pthread_mutex_unlock(&in->lock);
5524
5525 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305526 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305527 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305528 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305529 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305530 in->standby = true;
5531 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305532 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5533 bytes_read = bytes;
5534 memset(buffer, 0, bytes);
5535 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005536 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005537 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305538 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305539 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005540 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305541 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005542}
5543
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005544static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005545{
5546 return 0;
5547}
5548
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005549static int add_remove_audio_effect(const struct audio_stream *stream,
5550 effect_handle_t effect,
5551 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005552{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005553 struct stream_in *in = (struct stream_in *)stream;
5554 int status = 0;
5555 effect_descriptor_t desc;
5556
5557 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005558 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5559
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005560 if (status != 0)
5561 return status;
5562
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005563 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005564 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08005565 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5566 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005567 in->enable_aec != enable &&
5568 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5569 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005570 if (!in->standby) {
5571 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5572 select_devices(in->dev, in->usecase);
5573 }
5574
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005575 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005576 if (in->enable_ns != enable &&
5577 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5578 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005579 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08005580 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5581 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005582 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5583 select_devices(in->dev, in->usecase);
5584 } else
5585 select_devices(in->dev, in->usecase);
5586 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005587 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005588 pthread_mutex_unlock(&in->dev->lock);
5589 pthread_mutex_unlock(&in->lock);
5590
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005591 return 0;
5592}
5593
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005594static int in_add_audio_effect(const struct audio_stream *stream,
5595 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005596{
Eric Laurent994a6932013-07-17 11:51:42 -07005597 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005598 return add_remove_audio_effect(stream, effect, true);
5599}
5600
5601static int in_remove_audio_effect(const struct audio_stream *stream,
5602 effect_handle_t effect)
5603{
Eric Laurent994a6932013-07-17 11:51:42 -07005604 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005605 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005606}
5607
Haynes Mathew George16081042017-05-31 17:16:49 -07005608static int in_stop(const struct audio_stream_in* stream)
5609{
5610 struct stream_in *in = (struct stream_in *)stream;
5611 struct audio_device *adev = in->dev;
5612
5613 int ret = -ENOSYS;
5614 ALOGV("%s", __func__);
5615 pthread_mutex_lock(&adev->lock);
5616 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5617 in->capture_started && in->pcm != NULL) {
5618 pcm_stop(in->pcm);
5619 ret = stop_input_stream(in);
5620 in->capture_started = false;
5621 }
5622 pthread_mutex_unlock(&adev->lock);
5623 return ret;
5624}
5625
5626static int in_start(const struct audio_stream_in* stream)
5627{
5628 struct stream_in *in = (struct stream_in *)stream;
5629 struct audio_device *adev = in->dev;
5630 int ret = -ENOSYS;
5631
5632 ALOGV("%s in %p", __func__, in);
5633 pthread_mutex_lock(&adev->lock);
5634 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5635 !in->capture_started && in->pcm != NULL) {
5636 if (!in->capture_started) {
5637 ret = start_input_stream(in);
5638 if (ret == 0) {
5639 in->capture_started = true;
5640 }
5641 }
5642 }
5643 pthread_mutex_unlock(&adev->lock);
5644 return ret;
5645}
5646
5647static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5648 int32_t min_size_frames,
5649 struct audio_mmap_buffer_info *info)
5650{
5651 struct stream_in *in = (struct stream_in *)stream;
5652 struct audio_device *adev = in->dev;
5653 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005654 unsigned int offset1 = 0;
5655 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005656 const char *step = "";
5657
5658 pthread_mutex_lock(&adev->lock);
5659 ALOGV("%s in %p", __func__, in);
5660
5661 if (info == NULL || min_size_frames == 0) {
5662 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5663 ret = -EINVAL;
5664 goto exit;
5665 }
5666 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5667 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5668 ALOGV("%s in %p", __func__, in);
5669 ret = -ENOSYS;
5670 goto exit;
5671 }
5672 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5673 if (in->pcm_device_id < 0) {
5674 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5675 __func__, in->pcm_device_id, in->usecase);
5676 ret = -EINVAL;
5677 goto exit;
5678 }
5679
5680 adjust_mmap_period_count(&in->config, min_size_frames);
5681
5682 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5683 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5684 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5685 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
5686 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5687 step = "open";
5688 ret = -ENODEV;
5689 goto exit;
5690 }
5691
5692 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5693 if (ret < 0) {
5694 step = "begin";
5695 goto exit;
5696 }
5697 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5698 info->burst_size_frames = in->config.period_size;
5699 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
5700
5701 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
5702 info->buffer_size_frames));
5703
5704 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
5705 if (ret < 0) {
5706 step = "commit";
5707 goto exit;
5708 }
5709
5710 in->standby = false;
5711 ret = 0;
5712
5713 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5714 __func__, info->shared_memory_address, info->buffer_size_frames);
5715
5716exit:
5717 if (ret != 0) {
5718 if (in->pcm == NULL) {
5719 ALOGE("%s: %s - %d", __func__, step, ret);
5720 } else {
5721 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
5722 pcm_close(in->pcm);
5723 in->pcm = NULL;
5724 }
5725 }
5726 pthread_mutex_unlock(&adev->lock);
5727 return ret;
5728}
5729
5730static int in_get_mmap_position(const struct audio_stream_in *stream,
5731 struct audio_mmap_position *position)
5732{
5733 struct stream_in *in = (struct stream_in *)stream;
5734 ALOGVV("%s", __func__);
5735 if (position == NULL) {
5736 return -EINVAL;
5737 }
5738 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
5739 return -ENOSYS;
5740 }
5741 if (in->pcm == NULL) {
5742 return -ENOSYS;
5743 }
5744 struct timespec ts = { 0, 0 };
5745 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
5746 if (ret < 0) {
5747 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
5748 return ret;
5749 }
5750 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
5751 return 0;
5752}
5753
Naresh Tannirudcb47c52018-06-25 16:23:32 +05305754static int in_get_active_microphones(const struct audio_stream_in *stream,
5755 struct audio_microphone_characteristic_t *mic_array,
5756 size_t *mic_count) {
5757 struct stream_in *in = (struct stream_in *)stream;
5758 struct audio_device *adev = in->dev;
5759 ALOGVV("%s", __func__);
5760
5761 lock_input_stream(in);
5762 pthread_mutex_lock(&adev->lock);
5763 int ret = platform_get_active_microphones(adev->platform,
5764 audio_channel_count_from_in_mask(in->channel_mask),
5765 in->usecase, mic_array, mic_count);
5766 pthread_mutex_unlock(&adev->lock);
5767 pthread_mutex_unlock(&in->lock);
5768
5769 return ret;
5770}
5771
5772static int adev_get_microphones(const struct audio_hw_device *dev,
5773 struct audio_microphone_characteristic_t *mic_array,
5774 size_t *mic_count) {
5775 struct audio_device *adev = (struct audio_device *)dev;
5776 ALOGVV("%s", __func__);
5777
5778 pthread_mutex_lock(&adev->lock);
5779 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
5780 pthread_mutex_unlock(&adev->lock);
5781
5782 return ret;
5783}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305784int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07005785 audio_io_handle_t handle,
5786 audio_devices_t devices,
5787 audio_output_flags_t flags,
5788 struct audio_config *config,
5789 struct audio_stream_out **stream_out,
5790 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005791{
5792 struct audio_device *adev = (struct audio_device *)dev;
5793 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305794 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005795 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005796 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05305797 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005798 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
5799 bool is_usb_dev = audio_is_usb_out_device(devices) &&
5800 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
5801 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005802
kunleizdff872d2018-08-20 14:40:33 +08005803 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08005804 is_usb_dev = false;
5805 devices = AUDIO_DEVICE_OUT_SPEAKER;
5806 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
5807 __func__, devices);
5808 }
5809
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005810 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005812 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
5813
Mingming Yin3a941d42016-02-17 18:08:05 -08005814 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
5815 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305816 devices, flags, &out->stream);
5817
5818
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005819 if (!out) {
5820 return -ENOMEM;
5821 }
5822
Haynes Mathew George204045b2015-02-25 20:32:03 -08005823 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005824 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305825 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08005826 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08005827 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5828
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005829 if (devices == AUDIO_DEVICE_NONE)
5830 devices = AUDIO_DEVICE_OUT_SPEAKER;
5831
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005832 out->flags = flags;
5833 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07005834 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07005835 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005836 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05305837 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05305838 if (out->channel_mask == AUDIO_CHANNEL_NONE)
5839 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
5840 else
5841 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07005842 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005843 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08005844 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305845 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305846 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305847 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005848 out->hal_output_suspend_supported = 0;
5849 out->dynamic_pm_qos_config_supported = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005850
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05305851 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05305852 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07005853 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
5854
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005855 if (audio_is_linear_pcm(out->format) &&
5856 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
5857 pthread_mutex_lock(&adev->lock);
5858 if (is_hdmi) {
5859 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
5860 ret = read_hdmi_sink_caps(out);
5861 } else if (is_usb_dev) {
5862 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
5863 &config->format,
5864 &out->supported_formats[0],
5865 MAX_SUPPORTED_FORMATS,
5866 &config->channel_mask,
5867 &out->supported_channel_masks[0],
5868 MAX_SUPPORTED_CHANNEL_MASKS,
5869 &config->sample_rate,
5870 &out->supported_sample_rates[0],
5871 MAX_SUPPORTED_SAMPLE_RATES);
5872 ALOGV("plugged dev USB ret %d", ret);
5873 } else {
5874 ret = -1;
5875 }
5876 pthread_mutex_unlock(&adev->lock);
5877 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005878 if (ret == -ENOSYS) {
5879 /* ignore and go with default */
5880 ret = 0;
5881 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005882 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08005883 goto error_open;
5884 }
5885 }
5886 }
5887
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005888 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07005889#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005890 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5891 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
5892 out->sample_rate == 32000 || out->sample_rate == 48000)) {
5893 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
5894 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
5895 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5896
5897 out->config = default_pcm_config_voip_copp;
5898 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5899 out->config.rate = out->sample_rate;
5900
5901#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05305902 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005903 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08005904 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005905 ret = voice_extn_compress_voip_open_output_stream(out);
5906 if (ret != 0) {
5907 ALOGE("%s: Compress voip output cannot be opened, error:%d",
5908 __func__, ret);
5909 goto error_open;
5910 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005911#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005912 } else if (audio_is_linear_pcm(out->format) &&
5913 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
5914 out->channel_mask = config->channel_mask;
5915 out->sample_rate = config->sample_rate;
5916 out->format = config->format;
5917 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
5918 // does this change?
5919 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
5920 out->config.rate = config->sample_rate;
5921 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
5922 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
5923 audio_bytes_per_sample(config->format));
5924 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07005925 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305926 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305927 pthread_mutex_lock(&adev->lock);
5928 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
5929 pthread_mutex_unlock(&adev->lock);
5930
5931 // reject offload during card offline to allow
5932 // fallback to s/w paths
5933 if (offline) {
5934 ret = -ENODEV;
5935 goto error_open;
5936 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005937
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005938 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
5939 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
5940 ALOGE("%s: Unsupported Offload information", __func__);
5941 ret = -EINVAL;
5942 goto error_open;
5943 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005944
Atul Khare3fa6e542017-08-09 00:56:17 +05305945 if (config->offload_info.format == 0)
5946 config->offload_info.format = config->format;
5947 if (config->offload_info.sample_rate == 0)
5948 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005949
Mingming Yin90310102013-11-13 16:57:00 -08005950 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305951 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07005952 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005953 ret = -EINVAL;
5954 goto error_open;
5955 }
5956
Ben Romberger0f8c87b2017-05-24 17:41:11 -07005957 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
5958 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
5959 (audio_extn_passthru_is_passthrough_stream(out)) &&
5960 !((config->sample_rate == 48000) ||
5961 (config->sample_rate == 96000) ||
5962 (config->sample_rate == 192000))) {
5963 ALOGE("%s: Unsupported sample rate %d for audio format %x",
5964 __func__, config->sample_rate, config->offload_info.format);
5965 ret = -EINVAL;
5966 goto error_open;
5967 }
5968
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005969 out->compr_config.codec = (struct snd_codec *)
5970 calloc(1, sizeof(struct snd_codec));
5971
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005972 if (!out->compr_config.codec) {
5973 ret = -ENOMEM;
5974 goto error_open;
5975 }
5976
Dhananjay Kumarac341582017-02-23 23:42:25 +05305977 out->stream.pause = out_pause;
5978 out->stream.resume = out_resume;
5979 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05305980 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305981 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07005982 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305983 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07005984 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05305985 } else {
5986 out->usecase = get_offload_usecase(adev, false /* is_compress */);
5987 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07005988 }
vivek mehta446c3962015-09-14 10:57:35 -07005989
5990 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005991 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5992 config->format == 0 && config->sample_rate == 0 &&
5993 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07005994 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08005995 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
5996 } else {
5997 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
5998 ret = -EEXIST;
5999 goto error_open;
6000 }
vivek mehta446c3962015-09-14 10:57:35 -07006001 }
6002
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006003 if (config->offload_info.channel_mask)
6004 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006005 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006006 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006007 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006008 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306009 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006010 ret = -EINVAL;
6011 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006012 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006013
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006014 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006015 out->sample_rate = config->offload_info.sample_rate;
6016
Mingming Yin3ee55c62014-08-04 14:23:35 -07006017 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006018
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306019 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306020 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306021 audio_extn_dolby_send_ddp_endp_params(adev);
6022 audio_extn_dolby_set_dmid(adev);
6023 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006024
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006025 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006026 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006027 out->compr_config.codec->bit_rate =
6028 config->offload_info.bit_rate;
6029 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306030 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006031 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306032 /* Update bit width only for non passthrough usecases.
6033 * For passthrough usecases, the output will always be opened @16 bit
6034 */
6035 if (!audio_extn_passthru_is_passthrough_stream(out))
6036 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306037
6038 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6039 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6040 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6041
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006042 /*TODO: Do we need to change it for passthrough */
6043 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006044
Manish Dewangana6fc5442015-08-24 20:30:31 +05306045 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6046 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306047 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306048 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306049 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6050 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306051
6052 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6053 AUDIO_FORMAT_PCM) {
6054
6055 /*Based on platform support, configure appropriate alsa format for corresponding
6056 *hal input format.
6057 */
6058 out->compr_config.codec->format = hal_format_to_alsa(
6059 config->offload_info.format);
6060
Ashish Jain83a6cc22016-06-28 14:34:17 +05306061 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306062 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306063 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306064
Dhananjay Kumarac341582017-02-23 23:42:25 +05306065 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306066 *hal input format and alsa format might differ based on platform support.
6067 */
6068 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306069 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306070
6071 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6072
6073 /* Check if alsa session is configured with the same format as HAL input format,
6074 * if not then derive correct fragment size needed to accomodate the
6075 * conversion of HAL input format to alsa format.
6076 */
6077 audio_extn_utils_update_direct_pcm_fragment_size(out);
6078
6079 /*if hal input and output fragment size is different this indicates HAL input format is
6080 *not same as the alsa format
6081 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306082 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306083 /*Allocate a buffer to convert input data to the alsa configured format.
6084 *size of convert buffer is equal to the size required to hold one fragment size
6085 *worth of pcm data, this is because flinger does not write more than fragment_size
6086 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306087 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6088 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306089 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6090 ret = -ENOMEM;
6091 goto error_open;
6092 }
6093 }
6094 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6095 out->compr_config.fragment_size =
6096 audio_extn_passthru_get_buffer_size(&config->offload_info);
6097 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6098 } else {
6099 out->compr_config.fragment_size =
6100 platform_get_compress_offload_buffer_size(&config->offload_info);
6101 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6102 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006103
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306104 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6105 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6106 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006107 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306108 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006109
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306110 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6111 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6112 }
6113
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006114 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6115 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006116
Manish Dewangan69426c82017-01-30 17:35:36 +05306117 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6118 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6119 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6120 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6121 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6122 } else {
6123 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6124 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006125
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306126 memset(&out->channel_map_param, 0,
6127 sizeof(struct audio_out_channel_map_param));
6128
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006129 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306130 out->send_next_track_params = false;
6131 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006132 out->offload_state = OFFLOAD_STATE_IDLE;
6133 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006134 out->writeAt.tv_sec = 0;
6135 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006136
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006137 audio_extn_dts_create_state_notifier_node(out->usecase);
6138
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006139 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6140 __func__, config->offload_info.version,
6141 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306142
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306143 /* Check if DSD audio format is supported in codec
6144 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306145 */
6146
6147 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306148 (!platform_check_codec_dsd_support(adev->platform) ||
6149 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306150 ret = -EINVAL;
6151 goto error_open;
6152 }
6153
Ashish Jain5106d362016-05-11 19:23:33 +05306154 /* Disable gapless if any of the following is true
6155 * passthrough playback
6156 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306157 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306158 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306159 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306160 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006161 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306162 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306163 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306164 check_and_set_gapless_mode(adev, false);
6165 } else
6166 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006167
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306168 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006169 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6170 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306171 if (config->format == AUDIO_FORMAT_DSD) {
6172 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6173 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6174 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006175
6176 create_offload_callback_thread(out);
6177
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006178 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006179 switch (config->sample_rate) {
6180 case 0:
6181 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6182 break;
6183 case 8000:
6184 case 16000:
6185 case 48000:
6186 out->sample_rate = config->sample_rate;
6187 break;
6188 default:
6189 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
6190 config->sample_rate);
6191 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6192 ret = -EINVAL;
6193 goto error_open;
6194 }
6195 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6196 switch (config->channel_mask) {
6197 case AUDIO_CHANNEL_NONE:
6198 case AUDIO_CHANNEL_OUT_STEREO:
6199 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6200 break;
6201 default:
6202 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
6203 config->channel_mask);
6204 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6205 ret = -EINVAL;
6206 goto error_open;
6207 }
6208 switch (config->format) {
6209 case AUDIO_FORMAT_DEFAULT:
6210 case AUDIO_FORMAT_PCM_16_BIT:
6211 out->format = AUDIO_FORMAT_PCM_16_BIT;
6212 break;
6213 default:
6214 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
6215 config->format);
6216 config->format = AUDIO_FORMAT_PCM_16_BIT;
6217 ret = -EINVAL;
6218 goto error_open;
6219 }
6220
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306221 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006222 if (ret != 0) {
6223 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006224 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006225 goto error_open;
6226 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006227 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006228 if (config->sample_rate == 0)
6229 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6230 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6231 config->sample_rate != 8000) {
6232 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6233 ret = -EINVAL;
6234 goto error_open;
6235 }
6236 out->sample_rate = config->sample_rate;
6237 out->config.rate = config->sample_rate;
6238 if (config->format == AUDIO_FORMAT_DEFAULT)
6239 config->format = AUDIO_FORMAT_PCM_16_BIT;
6240 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6241 config->format = AUDIO_FORMAT_PCM_16_BIT;
6242 ret = -EINVAL;
6243 goto error_open;
6244 }
6245 out->format = config->format;
6246 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
6247 out->config = pcm_config_afe_proxy_playback;
6248 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006249 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05306250 unsigned int channels = 0;
6251 /*Update config params to default if not set by the caller*/
6252 if (config->sample_rate == 0)
6253 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6254 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6255 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6256 if (config->format == AUDIO_FORMAT_DEFAULT)
6257 config->format = AUDIO_FORMAT_PCM_16_BIT;
6258
6259 channels = audio_channel_count_from_out_mask(out->channel_mask);
6260
Varun Balaraje49253e2017-07-06 19:48:56 +05306261 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6262 out->usecase = get_interactive_usecase(adev);
6263 out->config = pcm_config_low_latency;
6264 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306265 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006266 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6267 out->flags);
6268 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006269 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6270 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6271 out->config = pcm_config_mmap_playback;
6272 out->stream.start = out_start;
6273 out->stream.stop = out_stop;
6274 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6275 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306276 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6277 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006278 out->hal_output_suspend_supported =
6279 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6280 out->dynamic_pm_qos_config_supported =
6281 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6282 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006283 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6284 } else {
6285 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6286 //the mixer path will be a string similar to "low-latency-playback resume"
6287 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6288 strlcat(out->pm_qos_mixer_path,
6289 " resume", MAX_MIXER_PATH_LEN);
6290 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6291 out->pm_qos_mixer_path);
6292 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306293 out->config = pcm_config_low_latency;
6294 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6295 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6296 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306297 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6298 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6299 if (out->config.period_size <= 0) {
6300 ALOGE("Invalid configuration period size is not valid");
6301 ret = -EINVAL;
6302 goto error_open;
6303 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306304 } else {
6305 /* primary path is the default path selected if no other outputs are available/suitable */
6306 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6307 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6308 }
6309 out->hal_ip_format = format = out->format;
6310 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6311 out->hal_op_format = pcm_format_to_hal(out->config.format);
6312 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6313 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006314 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306315 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306316 if (out->hal_ip_format != out->hal_op_format) {
6317 uint32_t buffer_size = out->config.period_size *
6318 format_to_bitwidth_table[out->hal_op_format] *
6319 out->config.channels;
6320 out->convert_buffer = calloc(1, buffer_size);
6321 if (out->convert_buffer == NULL){
6322 ALOGE("Allocation failed for convert buffer for size %d",
6323 out->compr_config.fragment_size);
6324 ret = -ENOMEM;
6325 goto error_open;
6326 }
6327 ALOGD("Convert buffer allocated of size %d", buffer_size);
6328 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006329 }
6330
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006331 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6332 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306333
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006334 /* TODO remove this hardcoding and check why width is zero*/
6335 if (out->bit_width == 0)
6336 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306337 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006338 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006339 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306340 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306341 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006342 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6343 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6344 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006345 if(adev->primary_output == NULL)
6346 adev->primary_output = out;
6347 else {
6348 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006349 ret = -EEXIST;
6350 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006351 }
6352 }
6353
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006354 /* Check if this usecase is already existing */
6355 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006356 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6357 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006358 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006359 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006360 ret = -EEXIST;
6361 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006362 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006363
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006364 pthread_mutex_unlock(&adev->lock);
6365
6366 out->stream.common.get_sample_rate = out_get_sample_rate;
6367 out->stream.common.set_sample_rate = out_set_sample_rate;
6368 out->stream.common.get_buffer_size = out_get_buffer_size;
6369 out->stream.common.get_channels = out_get_channels;
6370 out->stream.common.get_format = out_get_format;
6371 out->stream.common.set_format = out_set_format;
6372 out->stream.common.standby = out_standby;
6373 out->stream.common.dump = out_dump;
6374 out->stream.common.set_parameters = out_set_parameters;
6375 out->stream.common.get_parameters = out_get_parameters;
6376 out->stream.common.add_audio_effect = out_add_audio_effect;
6377 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6378 out->stream.get_latency = out_get_latency;
6379 out->stream.set_volume = out_set_volume;
6380 out->stream.write = out_write;
6381 out->stream.get_render_position = out_get_render_position;
6382 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006383 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006384
Haynes Mathew George16081042017-05-31 17:16:49 -07006385 if (out->realtime)
6386 out->af_period_multiplier = af_period_multiplier;
6387 else
6388 out->af_period_multiplier = 1;
6389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006390 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006391 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006392 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006393
6394 config->format = out->stream.common.get_format(&out->stream.common);
6395 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6396 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05306397 register_format(out->format, out->supported_formats);
6398 register_channel_mask(out->channel_mask, out->supported_channel_masks);
6399 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006400
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306401 /*
6402 By locking output stream before registering, we allow the callback
6403 to update stream's state only after stream's initial state is set to
6404 adev state.
6405 */
6406 lock_output_stream(out);
6407 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6408 pthread_mutex_lock(&adev->lock);
6409 out->card_status = adev->card_status;
6410 pthread_mutex_unlock(&adev->lock);
6411 pthread_mutex_unlock(&out->lock);
6412
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006413 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306414 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006415 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006416
6417 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6418 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6419 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006420 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306421 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006422 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006423 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306424 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006425 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6426 out->usecase, PCM_PLAYBACK);
6427 hdlr_stream_cfg.flags = out->flags;
6428 hdlr_stream_cfg.type = PCM_PLAYBACK;
6429 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6430 &hdlr_stream_cfg);
6431 if (ret) {
6432 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6433 out->adsp_hdlr_stream_handle = NULL;
6434 }
6435 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306436 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006437 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006438 if (ret < 0) {
6439 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6440 out->ip_hdlr_handle = NULL;
6441 }
6442 }
Eric Laurent994a6932013-07-17 11:51:42 -07006443 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006444 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006445
6446error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306447 if (out->convert_buffer)
6448 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006449 free(out);
6450 *stream_out = NULL;
6451 ALOGD("%s: exit: ret %d", __func__, ret);
6452 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006453}
6454
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306455void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006456 struct audio_stream_out *stream)
6457{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006458 struct stream_out *out = (struct stream_out *)stream;
6459 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006460 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006461
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006462 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306463
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306464 // must deregister from sndmonitor first to prevent races
6465 // between the callback and close_stream
6466 audio_extn_snd_mon_unregister_listener(out);
6467
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006468 /* close adsp hdrl session before standby */
6469 if (out->adsp_hdlr_stream_handle) {
6470 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6471 if (ret)
6472 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6473 out->adsp_hdlr_stream_handle = NULL;
6474 }
6475
Manish Dewangan21a850a2017-08-14 12:03:55 +05306476 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006477 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6478 out->ip_hdlr_handle = NULL;
6479 }
6480
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006481 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306482 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006483 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306484 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306485 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006486 if(ret != 0)
6487 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6488 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006489 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006490 out_standby(&stream->common);
6491
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006492 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006493 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006494 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006495 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006496 if (out->compr_config.codec != NULL)
6497 free(out->compr_config.codec);
6498 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006499
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306500 out->a2dp_compress_mute = false;
6501
Varun Balaraje49253e2017-07-06 19:48:56 +05306502 if (is_interactive_usecase(out->usecase))
6503 free_interactive_usecase(adev, out->usecase);
6504
Ashish Jain83a6cc22016-06-28 14:34:17 +05306505 if (out->convert_buffer != NULL) {
6506 free(out->convert_buffer);
6507 out->convert_buffer = NULL;
6508 }
6509
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006510 if (adev->voice_tx_output == out)
6511 adev->voice_tx_output = NULL;
6512
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306513 if (adev->primary_output == out)
6514 adev->primary_output = NULL;
6515
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006516 pthread_cond_destroy(&out->cond);
6517 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006518 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006519 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006520}
6521
6522static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6523{
6524 struct audio_device *adev = (struct audio_device *)dev;
6525 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006526 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006527 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006528 int ret;
6529 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006530
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006531 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006532 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006533
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306534 if (!parms)
6535 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306536
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306537 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6538 if (ret >= 0) {
6539 /* When set to false, HAL should disable EC and NS */
6540 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6541 adev->bt_sco_on = true;
6542 else
6543 adev->bt_sco_on = false;
6544 }
6545
Naresh Tanniru4c630392014-05-12 01:05:52 +05306546 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006547 status = voice_set_parameters(adev, parms);
6548 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006549 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006550
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006551 status = platform_set_parameters(adev->platform, parms);
6552 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006553 goto done;
6554
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006555 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6556 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006557 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006558 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6559 adev->bluetooth_nrec = true;
6560 else
6561 adev->bluetooth_nrec = false;
6562 }
6563
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006564 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6565 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006566 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6567 adev->screen_off = false;
6568 else
6569 adev->screen_off = true;
6570 }
6571
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006572 ret = str_parms_get_int(parms, "rotation", &val);
6573 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006574 bool reverse_speakers = false;
6575 switch(val) {
6576 // FIXME: note that the code below assumes that the speakers are in the correct placement
6577 // relative to the user when the device is rotated 90deg from its default rotation. This
6578 // assumption is device-specific, not platform-specific like this code.
6579 case 270:
6580 reverse_speakers = true;
6581 break;
6582 case 0:
6583 case 90:
6584 case 180:
6585 break;
6586 default:
6587 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006588 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006589 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006590 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006591 // check and set swap
6592 // - check if orientation changed and speaker active
6593 // - set rotation and cache the rotation value
6594 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006595 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006596 }
6597
Mingming Yin514a8bc2014-07-29 15:22:21 -07006598 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6599 if (ret >= 0) {
6600 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6601 adev->bt_wb_speech_enabled = true;
6602 else
6603 adev->bt_wb_speech_enabled = false;
6604 }
6605
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006606 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6607 if (ret >= 0) {
6608 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306609 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08006610 if (audio_is_output_device(val) &&
6611 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006612 ALOGV("cache new ext disp type and edid");
6613 ret = platform_get_ext_disp_type(adev->platform);
6614 if (ret < 0) {
6615 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05306616 } else {
6617 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006618 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306619 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07006620 /*
6621 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6622 * Per AudioPolicyManager, USB device is higher priority than WFD.
6623 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6624 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6625 * starting voice call on USB
6626 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006627 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306628 if (ret >= 0)
6629 audio_extn_usb_add_device(device, atoi(value));
6630
Zhou Song6f862822017-11-06 17:27:57 +08006631 if (!audio_extn_usb_is_tunnel_supported()) {
6632 ALOGV("detected USB connect .. disable proxy");
6633 adev->allow_afe_proxy_usage = false;
6634 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006635 }
6636 }
6637
6638 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6639 if (ret >= 0) {
6640 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306641 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07006642 /*
6643 * The HDMI / Displayport disconnect handling has been moved to
6644 * audio extension to ensure that its parameters are not
6645 * invalidated prior to updating sysfs of the disconnect event
6646 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6647 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306648 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006649 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306650 if (ret >= 0)
6651 audio_extn_usb_remove_device(device, atoi(value));
6652
Zhou Song6f862822017-11-06 17:27:57 +08006653 if (!audio_extn_usb_is_tunnel_supported()) {
6654 ALOGV("detected USB disconnect .. enable proxy");
6655 adev->allow_afe_proxy_usage = true;
6656 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006657 }
6658 }
6659
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306660 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6661 if (ret >= 0) {
6662 struct audio_usecase *usecase;
6663 struct listnode *node;
6664 list_for_each(node, &adev->usecase_list) {
6665 usecase = node_to_item(node, struct audio_usecase, list);
6666 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07006667 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306668 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08006669
6670 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306671 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08006672 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306673 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306674 //force device switch to re configure encoder
6675 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306676 audio_extn_a2dp_set_handoff_mode(false);
6677 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306678 break;
6679 }
6680 }
6681 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006682
6683 //handle vr audio setparam
6684 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6685 value, sizeof(value));
6686 if (ret >= 0) {
6687 ALOGI("Setting vr mode to be %s", value);
6688 if (!strncmp(value, "true", 4)) {
6689 adev->vr_audio_mode_enabled = true;
6690 ALOGI("Setting vr mode to true");
6691 } else if (!strncmp(value, "false", 5)) {
6692 adev->vr_audio_mode_enabled = false;
6693 ALOGI("Setting vr mode to false");
6694 } else {
6695 ALOGI("wrong vr mode set");
6696 }
6697 }
6698
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306699 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006700done:
6701 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006702 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306703error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006704 ALOGV("%s: exit with code(%d)", __func__, status);
6705 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006706}
6707
6708static char* adev_get_parameters(const struct audio_hw_device *dev,
6709 const char *keys)
6710{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006711 struct audio_device *adev = (struct audio_device *)dev;
6712 struct str_parms *reply = str_parms_create();
6713 struct str_parms *query = str_parms_create_str(keys);
6714 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05306715 char value[256] = {0};
6716 int ret = 0;
6717
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006718 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006719 if (reply) {
6720 str_parms_destroy(reply);
6721 }
6722 if (query) {
6723 str_parms_destroy(query);
6724 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006725 ALOGE("adev_get_parameters: failed to create query or reply");
6726 return NULL;
6727 }
6728
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006729 //handle vr audio getparam
6730
6731 ret = str_parms_get_str(query,
6732 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6733 value, sizeof(value));
6734
6735 if (ret >= 0) {
6736 bool vr_audio_enabled = false;
6737 pthread_mutex_lock(&adev->lock);
6738 vr_audio_enabled = adev->vr_audio_mode_enabled;
6739 pthread_mutex_unlock(&adev->lock);
6740
6741 ALOGI("getting vr mode to %d", vr_audio_enabled);
6742
6743 if (vr_audio_enabled) {
6744 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6745 "true");
6746 goto exit;
6747 } else {
6748 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6749 "false");
6750 goto exit;
6751 }
6752 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006753
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006754 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006755 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08006756 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006757 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05306758 pthread_mutex_unlock(&adev->lock);
6759
Naresh Tannirud7205b62014-06-20 02:54:48 +05306760exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006761 str = str_parms_to_str(reply);
6762 str_parms_destroy(query);
6763 str_parms_destroy(reply);
6764
6765 ALOGV("%s: exit: returns - %s", __func__, str);
6766 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006767}
6768
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006769static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006770{
6771 return 0;
6772}
6773
6774static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
6775{
Haynes Mathew George5191a852013-09-11 14:19:36 -07006776 int ret;
6777 struct audio_device *adev = (struct audio_device *)dev;
6778 pthread_mutex_lock(&adev->lock);
6779 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07006780 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07006781 pthread_mutex_unlock(&adev->lock);
6782 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006783}
6784
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006785static int adev_set_master_volume(struct audio_hw_device *dev __unused,
6786 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006787{
6788 return -ENOSYS;
6789}
6790
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006791static int adev_get_master_volume(struct audio_hw_device *dev __unused,
6792 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006793{
6794 return -ENOSYS;
6795}
6796
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006797static int adev_set_master_mute(struct audio_hw_device *dev __unused,
6798 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006799{
6800 return -ENOSYS;
6801}
6802
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006803static int adev_get_master_mute(struct audio_hw_device *dev __unused,
6804 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006805{
6806 return -ENOSYS;
6807}
6808
6809static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
6810{
6811 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07006812 struct listnode *node;
6813 struct audio_usecase *usecase = NULL;
6814 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006815 pthread_mutex_lock(&adev->lock);
6816 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006817 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006818 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08006819 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07006820 list_for_each(node, &adev->usecase_list) {
6821 usecase = node_to_item(node, struct audio_usecase, list);
6822 if (usecase->type == VOICE_CALL)
6823 break;
6824 }
6825 if (usecase &&
6826 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
6827 ret = audio_extn_usb_check_and_set_svc_int(usecase,
6828 true);
6829 if (ret != 0) {
6830 /* default service interval was successfully updated,
6831 reopen USB backend with new service interval */
6832 check_usecases_codec_backend(adev,
6833 usecase,
6834 usecase->out_snd_device);
6835 }
6836 }
6837
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006838 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07006839 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006840 adev->current_call_output = NULL;
6841 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006842 }
6843 pthread_mutex_unlock(&adev->lock);
6844 return 0;
6845}
6846
6847static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
6848{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006849 int ret;
6850
6851 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08006852 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006853 ret = voice_set_mic_mute((struct audio_device *)dev, state);
6854 pthread_mutex_unlock(&adev->lock);
6855
6856 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006857}
6858
6859static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
6860{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006861 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006862 return 0;
6863}
6864
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006865static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006866 const struct audio_config *config)
6867{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006868 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006869
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006870 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
6871 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006872}
6873
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006874static bool adev_input_allow_hifi_record(struct audio_device *adev,
6875 audio_devices_t devices,
6876 audio_input_flags_t flags,
6877 audio_source_t source) {
6878 const bool allowed = true;
6879
6880 if (!audio_is_usb_in_device(devices))
6881 return !allowed;
6882
6883 switch (flags) {
6884 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006885 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07006886 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
6887 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006888 default:
6889 return !allowed;
6890 }
6891
6892 switch (source) {
6893 case AUDIO_SOURCE_DEFAULT:
6894 case AUDIO_SOURCE_MIC:
6895 case AUDIO_SOURCE_UNPROCESSED:
6896 break;
6897 default:
6898 return !allowed;
6899 }
6900
6901 switch (adev->mode) {
6902 case 0:
6903 break;
6904 default:
6905 return !allowed;
6906 }
6907
6908 return allowed;
6909}
6910
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006911static int adev_update_voice_comm_input_stream(struct stream_in *in,
6912 struct audio_config *config)
6913{
6914 bool valid_rate = (config->sample_rate == 8000 ||
6915 config->sample_rate == 16000 ||
6916 config->sample_rate == 32000 ||
6917 config->sample_rate == 48000);
6918 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
6919
6920#ifndef COMPRESS_VOIP_ENABLED
kunleizd96526c2018-04-09 11:12:32 +08006921 if (valid_rate && valid_ch &&
6922 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006923 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6924 in->config = default_pcm_config_voip_copp;
6925 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
6926 DEFAULT_VOIP_BUF_DURATION_MS,
6927 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6928 } else {
kunleizbdd9ad02018-04-24 10:53:17 +08006929 ALOGW("%s No valid input in voip, use defaults"
6930 "sample rate %u, channel mask 0x%X",
6931 __func__, config->sample_rate, in->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006932 }
6933 in->config.rate = config->sample_rate;
6934 in->sample_rate = config->sample_rate;
6935#else
6936 //XXX needed for voice_extn_compress_voip_open_input_stream
6937 in->config.rate = config->sample_rate;
6938 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6939 voice_extn_compress_voip_is_active(in->dev)) &&
6940 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6941 valid_rate && valid_ch) {
6942 voice_extn_compress_voip_open_input_stream(in);
6943 // update rate entries to match config from AF
6944 in->config.rate = config->sample_rate;
6945 in->sample_rate = config->sample_rate;
6946 } else {
6947 ALOGW("%s compress voip not active, use defaults", __func__);
6948 }
6949#endif
6950 return 0;
6951}
6952
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006953static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006954 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006955 audio_devices_t devices,
6956 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006957 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306958 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006959 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006960 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006961{
6962 struct audio_device *adev = (struct audio_device *)dev;
6963 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006964 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006965 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006966 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306967 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006968 bool is_usb_dev = audio_is_usb_in_device(devices);
6969 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
6970 devices,
6971 flags,
6972 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306973
kunleizdff872d2018-08-20 14:40:33 +08006974 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006975 is_usb_dev = false;
6976 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
6977 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
6978 __func__, devices);
6979 }
6980
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006981 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006982
6983 if (!(is_usb_dev && may_use_hifi_record)) {
6984 if (config->sample_rate == 0)
6985 config->sample_rate = 48000;
6986 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6987 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
6988 if (config->format == AUDIO_FORMAT_DEFAULT)
6989 config->format = AUDIO_FORMAT_PCM_16_BIT;
6990
6991 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
6992
6993 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
6994 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05306995 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006996
6997 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006998
6999 if (!in) {
7000 ALOGE("failed to allocate input stream");
7001 return -ENOMEM;
7002 }
7003
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307004 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307005 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7006 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007007 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007008 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007009
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007010 in->stream.common.get_sample_rate = in_get_sample_rate;
7011 in->stream.common.set_sample_rate = in_set_sample_rate;
7012 in->stream.common.get_buffer_size = in_get_buffer_size;
7013 in->stream.common.get_channels = in_get_channels;
7014 in->stream.common.get_format = in_get_format;
7015 in->stream.common.set_format = in_set_format;
7016 in->stream.common.standby = in_standby;
7017 in->stream.common.dump = in_dump;
7018 in->stream.common.set_parameters = in_set_parameters;
7019 in->stream.common.get_parameters = in_get_parameters;
7020 in->stream.common.add_audio_effect = in_add_audio_effect;
7021 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7022 in->stream.set_gain = in_set_gain;
7023 in->stream.read = in_read;
7024 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307025 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007026
7027 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007028 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007029 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007030 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007031 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007032 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007033 in->bit_width = 16;
7034 in->af_period_multiplier = 1;
7035
7036 /* Update config params with the requested sample rate and channels */
7037 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
7038 (adev->mode != AUDIO_MODE_IN_CALL)) {
7039 ret = -EINVAL;
7040 goto err_open;
7041 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007042
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007043 if (is_usb_dev && may_use_hifi_record) {
7044 /* HiFi record selects an appropriate format, channel, rate combo
7045 depending on sink capabilities*/
7046 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7047 &config->format,
7048 &in->supported_formats[0],
7049 MAX_SUPPORTED_FORMATS,
7050 &config->channel_mask,
7051 &in->supported_channel_masks[0],
7052 MAX_SUPPORTED_CHANNEL_MASKS,
7053 &config->sample_rate,
7054 &in->supported_sample_rates[0],
7055 MAX_SUPPORTED_SAMPLE_RATES);
7056 if (ret != 0) {
7057 ret = -EINVAL;
7058 goto err_open;
7059 }
7060 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007061 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307062 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05307063 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
7064 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
7065 in->config.format = PCM_FORMAT_S32_LE;
7066 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307067 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
7068 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
7069 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
7070 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7071 bool ret_error = false;
7072 in->bit_width = 24;
7073 /* 24 bit is restricted to UNPROCESSED source only,also format supported
7074 from HAL is 24_packed and 8_24
7075 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
7076 24_packed return error indicating supported format is 24_packed
7077 *> In case of any other source requesting 24 bit or float return error
7078 indicating format supported is 16 bit only.
7079
7080 on error flinger will retry with supported format passed
7081 */
7082 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
7083 (source != AUDIO_SOURCE_CAMCORDER)) {
7084 config->format = AUDIO_FORMAT_PCM_16_BIT;
7085 if (config->sample_rate > 48000)
7086 config->sample_rate = 48000;
7087 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07007088 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
7089 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307090 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
7091 ret_error = true;
7092 }
7093
7094 if (ret_error) {
7095 ret = -EINVAL;
7096 goto err_open;
7097 }
7098 }
7099
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007100 in->channel_mask = config->channel_mask;
7101 in->format = config->format;
7102
7103 in->usecase = USECASE_AUDIO_RECORD;
7104 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
7105 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
7106 is_low_latency = true;
7107#if LOW_LATENCY_CAPTURE_USE_CASE
7108 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
7109#endif
7110 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
7111 }
7112
7113 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
7114 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
7115 in->realtime = 0;
7116 in->usecase = USECASE_AUDIO_RECORD_MMAP;
7117 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07007118 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007119 in->stream.start = in_start;
7120 in->stream.stop = in_stop;
7121 in->stream.create_mmap_buffer = in_create_mmap_buffer;
7122 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007123 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007124 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
7125 } else if (in->realtime) {
7126 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07007127 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007128 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007129 in->sample_rate = in->config.rate;
7130 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07007131 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007132 in->usecase = USECASE_AUDIO_RECORD_HIFI;
7133 in->config = pcm_config_audio_capture;
7134 frame_size = audio_stream_in_frame_size(&in->stream);
7135 buffer_size = get_input_buffer_size(config->sample_rate,
7136 config->format,
7137 channel_count,
7138 false /*is_low_latency*/);
7139 in->config.period_size = buffer_size / frame_size;
7140 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007141 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07007142 switch (config->format) {
7143 case AUDIO_FORMAT_PCM_32_BIT:
7144 in->bit_width = 32;
7145 break;
7146 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
7147 case AUDIO_FORMAT_PCM_8_24_BIT:
7148 in->bit_width = 24;
7149 break;
7150 default:
7151 in->bit_width = 16;
7152 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007153 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007154 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007155 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05307156 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007157 if (config->sample_rate == 0)
7158 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7159 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
7160 config->sample_rate != 8000) {
7161 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7162 ret = -EINVAL;
7163 goto err_open;
7164 }
7165 if (config->format == AUDIO_FORMAT_DEFAULT)
7166 config->format = AUDIO_FORMAT_PCM_16_BIT;
7167 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
7168 config->format = AUDIO_FORMAT_PCM_16_BIT;
7169 ret = -EINVAL;
7170 goto err_open;
7171 }
7172
7173 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
7174 in->config = pcm_config_afe_proxy_record;
7175 in->config.channels = channel_count;
7176 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307177 in->sample_rate = config->sample_rate;
Haynes Mathew George46740472017-10-27 18:40:12 -07007178 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05307179 int ret_val;
7180 pthread_mutex_lock(&adev->lock);
7181 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
7182 in, config, &channel_mask_updated);
7183 pthread_mutex_unlock(&adev->lock);
7184
7185 if (!ret_val) {
7186 if (channel_mask_updated == true) {
7187 ALOGD("%s: return error to retry with updated channel mask (%#x)",
7188 __func__, config->channel_mask);
7189 ret = -EINVAL;
7190 goto err_open;
7191 }
7192 ALOGD("%s: created multi-channel session succesfully",__func__);
7193 } else if (audio_extn_compr_cap_enabled() &&
7194 audio_extn_compr_cap_format_supported(config->format) &&
7195 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
7196 audio_extn_compr_cap_init(in);
7197 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05307198 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05307199 ret = audio_extn_cin_configure_input_stream(in);
7200 if (ret)
7201 goto err_open;
7202 } else {
7203 in->config = pcm_config_audio_capture;
7204 in->config.rate = config->sample_rate;
7205 in->config.format = pcm_format_from_audio_format(config->format);
7206 in->config.channels = channel_count;
7207 in->sample_rate = config->sample_rate;
7208 in->format = config->format;
7209 frame_size = audio_stream_in_frame_size(&in->stream);
7210 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07007211 config->format,
7212 channel_count,
7213 is_low_latency);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307214 in->config.period_size = buffer_size / frame_size;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007215
Revathi Uddarajud2634032017-12-07 14:42:34 +05307216 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
7217 /* optionally use VOIP usecase depending on config(s) */
7218 ret = adev_update_voice_comm_input_stream(in, config);
7219 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007220
Revathi Uddarajud2634032017-12-07 14:42:34 +05307221 if (ret) {
7222 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
7223 goto err_open;
7224 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007225 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007226 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307227 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7228 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007229 devices, flags, in->format,
7230 in->sample_rate, in->bit_width,
7231 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307232 register_format(in->format, in->supported_formats);
7233 register_channel_mask(in->channel_mask, in->supported_channel_masks);
7234 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307235
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007236 /* This stream could be for sound trigger lab,
7237 get sound trigger pcm if present */
7238 audio_extn_sound_trigger_check_and_get_session(in);
7239
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307240 lock_input_stream(in);
7241 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
7242 pthread_mutex_lock(&adev->lock);
7243 in->card_status = adev->card_status;
7244 pthread_mutex_unlock(&adev->lock);
7245 pthread_mutex_unlock(&in->lock);
7246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007247 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07007248 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007249 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007250
7251err_open:
7252 free(in);
7253 *stream_in = NULL;
7254 return ret;
7255}
7256
7257static void adev_close_input_stream(struct audio_hw_device *dev,
7258 struct audio_stream_in *stream)
7259{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007260 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007261 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007262 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307263
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307264 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007265
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307266 // must deregister from sndmonitor first to prevent races
7267 // between the callback and close_stream
7268 audio_extn_snd_mon_unregister_listener(stream);
7269
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307270 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07007271 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307272
Pallavid7c7a272018-01-16 11:22:55 +05307273 if (in == NULL) {
7274 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
7275 return;
7276 }
7277
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007278 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307279 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007280 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307281 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007282 if (ret != 0)
7283 ALOGE("%s: Compress voip input cannot be closed, error:%d",
7284 __func__, ret);
7285 } else
7286 in_standby(&stream->common);
7287
Revathi Uddarajud2634032017-12-07 14:42:34 +05307288 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07007289 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007290 audio_extn_ssr_deinit();
7291 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007292
Garmond Leunge2433c32017-09-28 21:51:22 -07007293 if (audio_extn_ffv_get_stream() == in) {
7294 audio_extn_ffv_stream_deinit();
7295 }
7296
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307297 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07007298 audio_extn_compr_cap_format_supported(in->config.format))
7299 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05307300
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307301 if (audio_extn_cin_attached_usecase(in->usecase))
7302 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007303
Mingming Yinfd7607b2016-01-22 12:48:44 -08007304 if (in->is_st_session) {
7305 ALOGV("%s: sound trigger pcm stop lab", __func__);
7306 audio_extn_sound_trigger_stop_lab(in);
7307 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007308 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307309 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007310 return;
7311}
7312
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307313int adev_create_audio_patch(struct audio_hw_device *dev,
7314 unsigned int num_sources,
7315 const struct audio_port_config *sources,
7316 unsigned int num_sinks,
7317 const struct audio_port_config *sinks,
7318 audio_patch_handle_t *handle)
7319{
7320
7321
7322 return audio_extn_hw_loopback_create_audio_patch(dev,
7323 num_sources,
7324 sources,
7325 num_sinks,
7326 sinks,
7327 handle);
7328
7329}
7330
7331int adev_release_audio_patch(struct audio_hw_device *dev,
7332 audio_patch_handle_t handle)
7333{
7334 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
7335}
7336
7337int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
7338{
7339 return audio_extn_hw_loopback_get_audio_port(dev, config);
7340}
7341
7342int adev_set_audio_port_config(struct audio_hw_device *dev,
7343 const struct audio_port_config *config)
7344{
7345 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
7346}
7347
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007348static int adev_dump(const audio_hw_device_t *device __unused,
7349 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007350{
7351 return 0;
7352}
7353
7354static int adev_close(hw_device_t *device)
7355{
7356 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07007357
7358 if (!adev)
7359 return 0;
7360
7361 pthread_mutex_lock(&adev_init_lock);
7362
7363 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307364 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007365 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08007366 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307367 audio_extn_utils_release_streams_cfg_lists(
7368 &adev->streams_output_cfg_list,
7369 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307370 if (audio_extn_qaf_is_enabled())
7371 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007372 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007373 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007374 free(adev->snd_dev_ref_cnt);
7375 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007376 if (adev->adm_deinit)
7377 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307378 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007379 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307380 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307381 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007382 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307383 if (adev->device_cfg_params) {
7384 free(adev->device_cfg_params);
7385 adev->device_cfg_params = NULL;
7386 }
Kiran Kandi910e1862013-10-29 13:29:42 -07007387 free(device);
7388 adev = NULL;
7389 }
7390 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007392 return 0;
7393}
7394
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007395/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
7396 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
7397 * just that it _might_ work.
7398 */
7399static int period_size_is_plausible_for_low_latency(int period_size)
7400{
7401 switch (period_size) {
7402 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07007403 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007404 case 240:
7405 case 320:
7406 case 480:
7407 return 1;
7408 default:
7409 return 0;
7410 }
7411}
7412
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307413static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
7414{
7415 bool is_snd_card_status = false;
7416 bool is_ext_device_status = false;
7417 char value[32];
7418 int card = -1;
7419 card_status_t status;
7420
7421 if (cookie != adev || !parms)
7422 return;
7423
7424 if (!parse_snd_card_status(parms, &card, &status)) {
7425 is_snd_card_status = true;
7426 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
7427 is_ext_device_status = true;
7428 } else {
7429 // not a valid event
7430 return;
7431 }
7432
7433 pthread_mutex_lock(&adev->lock);
7434 if (card == adev->snd_card || is_ext_device_status) {
7435 if (is_snd_card_status && adev->card_status != status) {
7436 adev->card_status = status;
7437 platform_snd_card_update(adev->platform, status);
7438 audio_extn_fm_set_parameters(adev, parms);
7439 } else if (is_ext_device_status) {
7440 platform_set_parameters(adev->platform, parms);
7441 }
7442 }
7443 pthread_mutex_unlock(&adev->lock);
7444 return;
7445}
7446
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307447/* out and adev lock held */
7448static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
7449{
7450 struct audio_usecase *uc_info;
7451 float left_p;
7452 float right_p;
7453 audio_devices_t devices;
7454
7455 uc_info = get_usecase_from_list(adev, out->usecase);
7456 if (uc_info == NULL) {
7457 ALOGE("%s: Could not find the usecase (%d) in the list",
7458 __func__, out->usecase);
7459 return -EINVAL;
7460 }
7461
7462 ALOGD("%s: enter: usecase(%d: %s)", __func__,
7463 out->usecase, use_case_table[out->usecase]);
7464
7465 if (restore) {
7466 // restore A2DP device for active usecases and unmute if required
7467 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
7468 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
7469 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
7470 select_devices(adev, uc_info->id);
7471 pthread_mutex_lock(&out->compr_mute_lock);
7472 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7473 (out->a2dp_compress_mute)) {
7474 out->a2dp_compress_mute = false;
7475 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
7476 }
7477 pthread_mutex_unlock(&out->compr_mute_lock);
7478 }
7479 } else {
7480 // mute compress stream if suspended
7481 pthread_mutex_lock(&out->compr_mute_lock);
7482 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7483 (!out->a2dp_compress_mute)) {
7484 if (!out->standby) {
7485 ALOGD("%s: selecting speaker and muting stream", __func__);
7486 devices = out->devices;
7487 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
7488 left_p = out->volume_l;
7489 right_p = out->volume_r;
7490 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7491 compress_pause(out->compr);
7492 out_set_compr_volume(&out->stream, (float)0, (float)0);
7493 out->a2dp_compress_mute = true;
7494 select_devices(adev, out->usecase);
7495 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7496 compress_resume(out->compr);
7497 out->devices = devices;
7498 out->volume_l = left_p;
7499 out->volume_r = right_p;
7500 }
7501 }
7502 pthread_mutex_unlock(&out->compr_mute_lock);
7503 }
7504 ALOGV("%s: exit", __func__);
7505 return 0;
7506}
7507
7508int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
7509{
7510 int ret = 0;
7511
7512 lock_output_stream(out);
7513 pthread_mutex_lock(&adev->lock);
7514
7515 ret = check_a2dp_restore_l(adev, out, restore);
7516
7517 pthread_mutex_unlock(&adev->lock);
7518 pthread_mutex_unlock(&out->lock);
7519 return ret;
7520}
7521
Haynes Mathew George01156f92018-04-13 15:29:54 -07007522void adev_on_battery_status_changed(bool charging)
7523{
7524 pthread_mutex_lock(&adev->lock);
7525 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
7526 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08007527 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07007528 pthread_mutex_unlock(&adev->lock);
7529}
7530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007531static int adev_open(const hw_module_t *module, const char *name,
7532 hw_device_t **device)
7533{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307534 int ret;
7535
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007536 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007537 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
7538
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007539 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07007540 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007541 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07007542 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007543 ALOGD("%s: returning existing instance of adev", __func__);
7544 ALOGD("%s: exit", __func__);
7545 pthread_mutex_unlock(&adev_init_lock);
7546 return 0;
7547 }
7548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007549 adev = calloc(1, sizeof(struct audio_device));
7550
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007551 if (!adev) {
7552 pthread_mutex_unlock(&adev_init_lock);
7553 return -ENOMEM;
7554 }
7555
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007556 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
7557
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05307558#ifdef DYNAMIC_LOG_ENABLED
7559 register_for_dynamic_logging("hal");
7560#endif
7561
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007562 adev->device.common.tag = HARDWARE_DEVICE_TAG;
7563 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7564 adev->device.common.module = (struct hw_module_t *)module;
7565 adev->device.common.close = adev_close;
7566
7567 adev->device.init_check = adev_init_check;
7568 adev->device.set_voice_volume = adev_set_voice_volume;
7569 adev->device.set_master_volume = adev_set_master_volume;
7570 adev->device.get_master_volume = adev_get_master_volume;
7571 adev->device.set_master_mute = adev_set_master_mute;
7572 adev->device.get_master_mute = adev_get_master_mute;
7573 adev->device.set_mode = adev_set_mode;
7574 adev->device.set_mic_mute = adev_set_mic_mute;
7575 adev->device.get_mic_mute = adev_get_mic_mute;
7576 adev->device.set_parameters = adev_set_parameters;
7577 adev->device.get_parameters = adev_get_parameters;
7578 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
7579 adev->device.open_output_stream = adev_open_output_stream;
7580 adev->device.close_output_stream = adev_close_output_stream;
7581 adev->device.open_input_stream = adev_open_input_stream;
7582 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307583 adev->device.create_audio_patch = adev_create_audio_patch;
7584 adev->device.release_audio_patch = adev_release_audio_patch;
7585 adev->device.get_audio_port = adev_get_audio_port;
7586 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007587 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307588 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007589
7590 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007591 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08007592 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007593 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007594 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007595 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08007596 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07007597 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307598 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07007599 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07007600 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007601 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08007602 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08007603 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007604 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05307605 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307606 adev->perf_lock_opts[0] = 0x101;
7607 adev->perf_lock_opts[1] = 0x20E;
7608 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007609 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007611 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07007612 adev->platform = platform_init(adev);
7613 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007614 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007615 free(adev->snd_dev_ref_cnt);
7616 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007617 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07007618 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7619 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08007620 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007621 return -EINVAL;
7622 }
Eric Laurentc4aef752013-09-12 17:45:53 -07007623
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307624 if (audio_extn_qaf_is_enabled()) {
7625 ret = audio_extn_qaf_init(adev);
7626 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007627 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307628 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007629 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307630 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7631 *device = NULL;
7632 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307633 return ret;
7634 }
7635
7636 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
7637 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
7638 }
7639
Eric Laurentc4aef752013-09-12 17:45:53 -07007640 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
7641 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
7642 if (adev->visualizer_lib == NULL) {
7643 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
7644 } else {
7645 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
7646 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007647 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007648 "visualizer_hal_start_output");
7649 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007650 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007651 "visualizer_hal_stop_output");
7652 }
7653 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05307654 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08007655 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007656 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307657 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007658 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07007659
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007660 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
7661 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
7662 if (adev->offload_effects_lib == NULL) {
7663 ALOGE("%s: DLOPEN failed for %s", __func__,
7664 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7665 } else {
7666 ALOGV("%s: DLOPEN successful for %s", __func__,
7667 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7668 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05307669 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007670 "offload_effects_bundle_hal_start_output");
7671 adev->offload_effects_stop_output =
7672 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
7673 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007674 adev->offload_effects_set_hpx_state =
7675 (int (*)(bool))dlsym(adev->offload_effects_lib,
7676 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05307677 adev->offload_effects_get_parameters =
7678 (void (*)(struct str_parms *, struct str_parms *))
7679 dlsym(adev->offload_effects_lib,
7680 "offload_effects_bundle_get_parameters");
7681 adev->offload_effects_set_parameters =
7682 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
7683 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007684 }
7685 }
7686
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007687 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
7688 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
7689 if (adev->adm_lib == NULL) {
7690 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
7691 } else {
7692 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
7693 adev->adm_init = (adm_init_t)
7694 dlsym(adev->adm_lib, "adm_init");
7695 adev->adm_deinit = (adm_deinit_t)
7696 dlsym(adev->adm_lib, "adm_deinit");
7697 adev->adm_register_input_stream = (adm_register_input_stream_t)
7698 dlsym(adev->adm_lib, "adm_register_input_stream");
7699 adev->adm_register_output_stream = (adm_register_output_stream_t)
7700 dlsym(adev->adm_lib, "adm_register_output_stream");
7701 adev->adm_deregister_stream = (adm_deregister_stream_t)
7702 dlsym(adev->adm_lib, "adm_deregister_stream");
7703 adev->adm_request_focus = (adm_request_focus_t)
7704 dlsym(adev->adm_lib, "adm_request_focus");
7705 adev->adm_abandon_focus = (adm_abandon_focus_t)
7706 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007707 adev->adm_set_config = (adm_set_config_t)
7708 dlsym(adev->adm_lib, "adm_set_config");
7709 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
7710 dlsym(adev->adm_lib, "adm_request_focus_v2");
7711 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
7712 dlsym(adev->adm_lib, "adm_is_noirq_avail");
7713 adev->adm_on_routing_change = (adm_on_routing_change_t)
7714 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007715 }
7716 }
7717
Mingming Yin514a8bc2014-07-29 15:22:21 -07007718 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007719 //initialize this to false for now,
7720 //this will be set to true through set param
7721 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07007722
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07007723 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007724 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007725 adev->dsp_bit_width_enforce_mode =
7726 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007727
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307728 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
7729 &adev->streams_output_cfg_list,
7730 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007731
Kiran Kandi910e1862013-10-29 13:29:42 -07007732 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007733
7734 char value[PROPERTY_VALUE_MAX];
7735 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007736 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007737 trial = atoi(value);
7738 if (period_size_is_plausible_for_low_latency(trial)) {
7739 pcm_config_low_latency.period_size = trial;
7740 pcm_config_low_latency.start_threshold = trial / 4;
7741 pcm_config_low_latency.avail_min = trial / 4;
7742 configured_low_latency_capture_period_size = trial;
7743 }
7744 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007745 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007746 trial = atoi(value);
7747 if (period_size_is_plausible_for_low_latency(trial)) {
7748 configured_low_latency_capture_period_size = trial;
7749 }
7750 }
7751
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08007752 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
7753
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007754 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007755 af_period_multiplier = atoi(value);
7756 if (af_period_multiplier < 0)
7757 af_period_multiplier = 2;
7758 else if (af_period_multiplier > 4)
7759 af_period_multiplier = 4;
7760
7761 ALOGV("new period_multiplier = %d", af_period_multiplier);
7762 }
7763
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007764 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007765 pthread_mutex_unlock(&adev_init_lock);
7766
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007767 if (adev->adm_init)
7768 adev->adm_data = adev->adm_init();
7769
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307770 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307771 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007772 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307773
7774 audio_extn_snd_mon_init();
7775 pthread_mutex_lock(&adev->lock);
7776 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
7777 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07007778 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
7779 /*
7780 * if the battery state callback happens before charging can be queried,
7781 * it will be guarded with the adev->lock held in the cb function and so
7782 * the callback value will reflect the latest state
7783 */
7784 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307785 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08007786 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
7787 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307788 /* Allocate memory for Device config params */
7789 adev->device_cfg_params = (struct audio_device_config_param*)
7790 calloc(platform_get_max_codec_backend(),
7791 sizeof(struct audio_device_config_param));
7792 if (adev->device_cfg_params == NULL)
7793 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307794
Eric Laurent994a6932013-07-17 11:51:42 -07007795 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007796 return 0;
7797}
7798
7799static struct hw_module_methods_t hal_module_methods = {
7800 .open = adev_open,
7801};
7802
7803struct audio_module HAL_MODULE_INFO_SYM = {
7804 .common = {
7805 .tag = HARDWARE_MODULE_TAG,
7806 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
7807 .hal_api_version = HARDWARE_HAL_API_VERSION,
7808 .id = AUDIO_HARDWARE_MODULE_ID,
7809 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08007810 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007811 .methods = &hal_module_methods,
7812 },
7813};