blob: 75b74f2b20ee3a3aede781020ec1bdb9bbe7ed5a [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
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053093#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053094#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070095
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070096#define PROXY_OPEN_RETRY_COUNT 100
97#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080098
Mingming Yin08c7e312015-03-16 18:10:58 -070099#ifdef USE_LL_AS_PRIMARY_OUTPUT
100#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
101#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
102#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800103#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700104#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
105#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800106
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700107#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700108#define DEFAULT_VOIP_BUF_DURATION_MS 20
109#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
110#define DEFAULT_VOIP_SAMP_RATE 48000
111
112#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
113
114struct pcm_config default_pcm_config_voip_copp = {
115 .channels = 1,
116 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
117 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
118 .period_count = 2,
119 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800120 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
121 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700122};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700123
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700124#define MIN_CHANNEL_COUNT 1
125#define DEFAULT_CHANNEL_COUNT 2
126#define MAX_HIFI_CHANNEL_COUNT 8
127
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700128static unsigned int configured_low_latency_capture_period_size =
129 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
130
Haynes Mathew George16081042017-05-31 17:16:49 -0700131#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
132#define MMAP_PERIOD_COUNT_MIN 32
133#define MMAP_PERIOD_COUNT_MAX 512
134#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
135
Eric Laurentb23d5282013-05-14 15:27:20 -0700136struct pcm_config pcm_config_deep_buffer = {
137 .channels = 2,
138 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
139 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
140 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
141 .format = PCM_FORMAT_S16_LE,
142 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
143 .stop_threshold = INT_MAX,
144 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
145};
146
147struct pcm_config pcm_config_low_latency = {
148 .channels = 2,
149 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
150 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
151 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
152 .format = PCM_FORMAT_S16_LE,
153 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
154 .stop_threshold = INT_MAX,
155 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
156};
157
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700158static int af_period_multiplier = 4;
159struct pcm_config pcm_config_rt = {
160 .channels = 2,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = ULL_PERIOD_SIZE, //1 ms
163 .period_count = 512, //=> buffer size is 512ms
164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
166 .stop_threshold = INT_MAX,
167 .silence_threshold = 0,
168 .silence_size = 0,
169 .avail_min = ULL_PERIOD_SIZE, //1 ms
170};
171
Eric Laurentb23d5282013-05-14 15:27:20 -0700172struct pcm_config pcm_config_hdmi_multi = {
173 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
174 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
175 .period_size = HDMI_MULTI_PERIOD_SIZE,
176 .period_count = HDMI_MULTI_PERIOD_COUNT,
177 .format = PCM_FORMAT_S16_LE,
178 .start_threshold = 0,
179 .stop_threshold = INT_MAX,
180 .avail_min = 0,
181};
182
Haynes Mathew George16081042017-05-31 17:16:49 -0700183struct pcm_config pcm_config_mmap_playback = {
184 .channels = 2,
185 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
186 .period_size = MMAP_PERIOD_SIZE,
187 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
188 .format = PCM_FORMAT_S16_LE,
189 .start_threshold = MMAP_PERIOD_SIZE*8,
190 .stop_threshold = INT32_MAX,
191 .silence_threshold = 0,
192 .silence_size = 0,
193 .avail_min = MMAP_PERIOD_SIZE, //1 ms
194};
195
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700196struct pcm_config pcm_config_hifi = {
197 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
198 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
199 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
200 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
201 .format = PCM_FORMAT_S24_3LE,
202 .start_threshold = 0,
203 .stop_threshold = INT_MAX,
204 .avail_min = 0,
205};
206
Eric Laurentb23d5282013-05-14 15:27:20 -0700207struct pcm_config pcm_config_audio_capture = {
208 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700209 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
210 .format = PCM_FORMAT_S16_LE,
211};
212
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700213struct pcm_config pcm_config_audio_capture_rt = {
214 .channels = 2,
215 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
216 .period_size = ULL_PERIOD_SIZE,
217 .period_count = 512,
218 .format = PCM_FORMAT_S16_LE,
219 .start_threshold = 0,
220 .stop_threshold = INT_MAX,
221 .silence_threshold = 0,
222 .silence_size = 0,
223 .avail_min = ULL_PERIOD_SIZE, //1 ms
224};
225
Haynes Mathew George16081042017-05-31 17:16:49 -0700226struct pcm_config pcm_config_mmap_capture = {
227 .channels = 2,
228 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
229 .period_size = MMAP_PERIOD_SIZE,
230 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
231 .format = PCM_FORMAT_S16_LE,
232 .start_threshold = 0,
233 .stop_threshold = INT_MAX,
234 .silence_threshold = 0,
235 .silence_size = 0,
236 .avail_min = MMAP_PERIOD_SIZE, //1 ms
237};
238
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700239#define AFE_PROXY_CHANNEL_COUNT 2
240#define AFE_PROXY_SAMPLING_RATE 48000
241
242#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
243#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
244
245struct pcm_config pcm_config_afe_proxy_playback = {
246 .channels = AFE_PROXY_CHANNEL_COUNT,
247 .rate = AFE_PROXY_SAMPLING_RATE,
248 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
249 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
250 .format = PCM_FORMAT_S16_LE,
251 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
252 .stop_threshold = INT_MAX,
253 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
254};
255
256#define AFE_PROXY_RECORD_PERIOD_SIZE 768
257#define AFE_PROXY_RECORD_PERIOD_COUNT 4
258
259struct pcm_config pcm_config_afe_proxy_record = {
260 .channels = AFE_PROXY_CHANNEL_COUNT,
261 .rate = AFE_PROXY_SAMPLING_RATE,
262 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
263 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
264 .format = PCM_FORMAT_S16_LE,
265 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
266 .stop_threshold = INT_MAX,
267 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
268};
269
Ashish Jainf1eaa582016-05-23 20:54:24 +0530270#define AUDIO_MAX_PCM_FORMATS 7
271
272const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
273 [AUDIO_FORMAT_DEFAULT] = 0,
274 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
275 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
276 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
277 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
278 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
279 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
280};
281
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800282const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700283 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
284 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700285 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
286 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700287 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700288 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700289 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
290 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
291 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
292 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
293 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
294 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
295 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
296 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700297 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
298 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700299 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700300
Eric Laurentb23d5282013-05-14 15:27:20 -0700301 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700302 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530303 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
304 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
305 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530306 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
307 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700308 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700309 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700310 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700311 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700312
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800313 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800314 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700315 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700316
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700317 [USECASE_VOICE2_CALL] = "voice2-call",
318 [USECASE_VOLTE_CALL] = "volte-call",
319 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800320 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800321 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
322 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800323 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700324 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
325 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
326 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800327 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
328 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
329 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
330
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700331 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
332 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700333 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
334 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700335
336 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
337 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530338 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700339
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530340 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530341 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
342 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700343
344 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
345 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530346 /* For Interactive Audio Streams */
347 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
348 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
349 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
350 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
351 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
352 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
353 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
354 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700355
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800356 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
357
358 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback"
Eric Laurentb23d5282013-05-14 15:27:20 -0700359};
360
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700361static const audio_usecase_t offload_usecases[] = {
362 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700363 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
364 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
365 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
366 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
367 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
368 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
369 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
370 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700371};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800372
Varun Balaraje49253e2017-07-06 19:48:56 +0530373static const audio_usecase_t interactive_usecases[] = {
374 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
375 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
376 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
377 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
378 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
379 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
380 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
381 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
382};
383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800384#define STRING_TO_ENUM(string) { #string, string }
385
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800386struct string_to_enum {
387 const char *name;
388 uint32_t value;
389};
390
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700391static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800392 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800393 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
394 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
395 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700396 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800397 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
398 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800399 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700400 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
401 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
402 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
403 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
404 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
405 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
406 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
407 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
408 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
409 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
410 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800411};
412
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700413static const struct string_to_enum formats_name_to_enum_table[] = {
414 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
415 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
416 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700417 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
418 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
419 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700420 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800421 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
422 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700423 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800424};
425
426//list of all supported sample rates by HDMI specification.
427static const int out_hdmi_sample_rates[] = {
428 32000, 44100, 48000, 88200, 96000, 176400, 192000,
429};
430
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700431static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800432 STRING_TO_ENUM(32000),
433 STRING_TO_ENUM(44100),
434 STRING_TO_ENUM(48000),
435 STRING_TO_ENUM(88200),
436 STRING_TO_ENUM(96000),
437 STRING_TO_ENUM(176400),
438 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700439};
440
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700441static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700442static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700443static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700444//cache last MBDRC cal step level
445static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700446
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530447static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
448static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800449static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530450static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530451
Vatsal Buchac09ae062018-11-14 13:25:08 +0530452#ifdef AUDIO_FEATURE_ENABLED_GCOV
453extern void __gcov_flush();
454static void enable_gcov()
455{
456 __gcov_flush();
457}
458#else
459static void enable_gcov()
460{
461}
462#endif
463
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700464static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
465 int flags __unused)
466{
467 int dir = 0;
468 switch (uc_id) {
469 case USECASE_AUDIO_RECORD_LOW_LATENCY:
470 dir = 1;
471 case USECASE_AUDIO_PLAYBACK_ULL:
472 break;
473 default:
474 return false;
475 }
476
477 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
478 PCM_PLAYBACK : PCM_CAPTURE);
479 if (adev->adm_is_noirq_avail)
480 return adev->adm_is_noirq_avail(adev->adm_data,
481 adev->snd_card, dev_id, dir);
482 return false;
483}
484
485static void register_out_stream(struct stream_out *out)
486{
487 struct audio_device *adev = out->dev;
488 if (is_offload_usecase(out->usecase) ||
489 !adev->adm_register_output_stream)
490 return;
491
492 // register stream first for backward compatibility
493 adev->adm_register_output_stream(adev->adm_data,
494 out->handle,
495 out->flags);
496
497 if (!adev->adm_set_config)
498 return;
499
500 if (out->realtime)
501 adev->adm_set_config(adev->adm_data,
502 out->handle,
503 out->pcm, &out->config);
504}
505
506static void register_in_stream(struct stream_in *in)
507{
508 struct audio_device *adev = in->dev;
509 if (!adev->adm_register_input_stream)
510 return;
511
512 adev->adm_register_input_stream(adev->adm_data,
513 in->capture_handle,
514 in->flags);
515
516 if (!adev->adm_set_config)
517 return;
518
519 if (in->realtime)
520 adev->adm_set_config(adev->adm_data,
521 in->capture_handle,
522 in->pcm,
523 &in->config);
524}
525
526static void request_out_focus(struct stream_out *out, long ns)
527{
528 struct audio_device *adev = out->dev;
529
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700530 if (adev->adm_request_focus_v2)
531 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
532 else if (adev->adm_request_focus)
533 adev->adm_request_focus(adev->adm_data, out->handle);
534}
535
536static void request_in_focus(struct stream_in *in, long ns)
537{
538 struct audio_device *adev = in->dev;
539
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700540 if (adev->adm_request_focus_v2)
541 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
542 else if (adev->adm_request_focus)
543 adev->adm_request_focus(adev->adm_data, in->capture_handle);
544}
545
546static void release_out_focus(struct stream_out *out)
547{
548 struct audio_device *adev = out->dev;
549
550 if (adev->adm_abandon_focus)
551 adev->adm_abandon_focus(adev->adm_data, out->handle);
552}
553
554static void release_in_focus(struct stream_in *in)
555{
556 struct audio_device *adev = in->dev;
557 if (adev->adm_abandon_focus)
558 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
559}
560
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530561static int parse_snd_card_status(struct str_parms *parms, int *card,
562 card_status_t *status)
563{
564 char value[32]={0};
565 char state[32]={0};
566
567 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
568 if (ret < 0)
569 return -1;
570
571 // sscanf should be okay as value is of max length 32.
572 // same as sizeof state.
573 if (sscanf(value, "%d,%s", card, state) < 2)
574 return -1;
575
576 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
577 CARD_STATUS_OFFLINE;
578 return 0;
579}
580
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700581static inline void adjust_frames_for_device_delay(struct stream_out *out,
582 uint32_t *dsp_frames) {
583 // Adjustment accounts for A2dp encoder latency with offload usecases
584 // Note: Encoder latency is returned in ms.
585 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
586 unsigned long offset =
587 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
588 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
589 }
590}
591
vivek mehtaa76401a2015-04-24 14:12:15 -0700592__attribute__ ((visibility ("default")))
593bool audio_hw_send_gain_dep_calibration(int level) {
594 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700595 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700596
597 pthread_mutex_lock(&adev_init_lock);
598
599 if (adev != NULL && adev->platform != NULL) {
600 pthread_mutex_lock(&adev->lock);
601 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700602
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530603 // cache level info for any of the use case which
604 // was not started.
605 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700606
vivek mehtaa76401a2015-04-24 14:12:15 -0700607 pthread_mutex_unlock(&adev->lock);
608 } else {
609 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
610 }
611
612 pthread_mutex_unlock(&adev_init_lock);
613
614 return ret_val;
615}
616
Ashish Jain5106d362016-05-11 19:23:33 +0530617static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
618{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800619 bool gapless_enabled = false;
620 const char *mixer_ctl_name = "Compress Gapless Playback";
621 struct mixer_ctl *ctl;
622
623 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700624 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530625
626 /*Disable gapless if its AV playback*/
627 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800628
629 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
630 if (!ctl) {
631 ALOGE("%s: Could not get ctl for mixer cmd - %s",
632 __func__, mixer_ctl_name);
633 return -EINVAL;
634 }
635
636 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
637 ALOGE("%s: Could not set gapless mode %d",
638 __func__, gapless_enabled);
639 return -EINVAL;
640 }
641 return 0;
642}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700643
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700644__attribute__ ((visibility ("default")))
645int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
646 int table_size) {
647 int ret_val = 0;
648 ALOGV("%s: enter ... ", __func__);
649
650 pthread_mutex_lock(&adev_init_lock);
651 if (adev == NULL) {
652 ALOGW("%s: adev is NULL .... ", __func__);
653 goto done;
654 }
655
656 pthread_mutex_lock(&adev->lock);
657 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
658 pthread_mutex_unlock(&adev->lock);
659done:
660 pthread_mutex_unlock(&adev_init_lock);
661 ALOGV("%s: exit ... ", __func__);
662 return ret_val;
663}
664
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700665static bool is_supported_format(audio_format_t format)
666{
Eric Laurent86e17132013-09-12 17:49:30 -0700667 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530668 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530669 format == AUDIO_FORMAT_AAC_LC ||
670 format == AUDIO_FORMAT_AAC_HE_V1 ||
671 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530672 format == AUDIO_FORMAT_AAC_ADTS_LC ||
673 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
674 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530675 format == AUDIO_FORMAT_AAC_LATM_LC ||
676 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
677 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530678 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
679 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530680 format == AUDIO_FORMAT_PCM_FLOAT ||
681 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700682 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530683 format == AUDIO_FORMAT_AC3 ||
684 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700685 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530686 format == AUDIO_FORMAT_DTS ||
687 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800688 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530689 format == AUDIO_FORMAT_ALAC ||
690 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530691 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530692 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800693 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530694 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700695 format == AUDIO_FORMAT_APTX ||
696 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800697 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700698
699 return false;
700}
701
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700702static inline bool is_mmap_usecase(audio_usecase_t uc_id)
703{
704 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
705 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
706}
707
Avinash Vaish71a8b972014-07-24 15:36:33 +0530708static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
709 struct audio_usecase *uc_info)
710{
711 struct listnode *node;
712 struct audio_usecase *usecase;
713
714 if (uc_info == NULL)
715 return -EINVAL;
716
717 /* Re-route all voice usecases on the shared backend other than the
718 specified usecase to new snd devices */
719 list_for_each(node, &adev->usecase_list) {
720 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800721 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530722 enable_audio_route(adev, usecase);
723 }
724 return 0;
725}
726
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530727static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530728{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530729 ALOGV("%s", __func__);
730 audio_route_apply_and_update_path(adev->audio_route,
731 "asrc-mode");
732 adev->asrc_mode_enabled = true;
733}
734
735static void disable_asrc_mode(struct audio_device *adev)
736{
737 ALOGV("%s", __func__);
738 audio_route_reset_and_update_path(adev->audio_route,
739 "asrc-mode");
740 adev->asrc_mode_enabled = false;
741}
742
743/*
744 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
745 * 44.1 or Native DSD backends are enabled for any of current use case.
746 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
747 * - Disable current mix path use case(Headphone backend) and re-enable it with
748 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
749 * e.g. Naitve DSD or Headphone 44.1 -> + 48
750 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530751static void check_and_set_asrc_mode(struct audio_device *adev,
752 struct audio_usecase *uc_info,
753 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530754{
755 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530756 int i, num_new_devices = 0;
757 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
758 /*
759 *Split snd device for new combo use case
760 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
761 */
762 if (platform_split_snd_device(adev->platform,
763 snd_device,
764 &num_new_devices,
765 split_new_snd_devices) == 0) {
766 for (i = 0; i < num_new_devices; i++)
767 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
768 } else {
769 int new_backend_idx = platform_get_backend_index(snd_device);
770 if (((new_backend_idx == HEADPHONE_BACKEND) ||
771 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
772 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
773 !adev->asrc_mode_enabled) {
774 struct listnode *node = NULL;
775 struct audio_usecase *uc = NULL;
776 struct stream_out *curr_out = NULL;
777 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
778 int i, num_devices, ret = 0;
779 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530780
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530781 list_for_each(node, &adev->usecase_list) {
782 uc = node_to_item(node, struct audio_usecase, list);
783 curr_out = (struct stream_out*) uc->stream.out;
784 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
785 /*
786 *Split snd device for existing combo use case
787 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
788 */
789 ret = platform_split_snd_device(adev->platform,
790 uc->out_snd_device,
791 &num_devices,
792 split_snd_devices);
793 if (ret < 0 || num_devices == 0) {
794 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
795 split_snd_devices[0] = uc->out_snd_device;
796 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800797 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530798 for (i = 0; i < num_devices; i++) {
799 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
800 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
801 if((new_backend_idx == HEADPHONE_BACKEND) &&
802 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
803 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
804 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
805 __func__);
806 enable_asrc_mode(adev);
807 break;
808 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
809 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
810 (usecase_backend_idx == HEADPHONE_BACKEND)) {
811 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
812 __func__);
813 disable_audio_route(adev, uc);
814 disable_snd_device(adev, uc->out_snd_device);
815 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
816 if (new_backend_idx == DSD_NATIVE_BACKEND)
817 audio_route_apply_and_update_path(adev->audio_route,
818 "hph-true-highquality-mode");
819 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
820 (curr_out->bit_width >= 24))
821 audio_route_apply_and_update_path(adev->audio_route,
822 "hph-highquality-mode");
823 enable_asrc_mode(adev);
824 enable_snd_device(adev, uc->out_snd_device);
825 enable_audio_route(adev, uc);
826 break;
827 }
828 }
829 // reset split devices count
830 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800831 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530832 if (adev->asrc_mode_enabled)
833 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530834 }
835 }
836 }
837}
838
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700839#ifdef DYNAMIC_ECNS_ENABLED
840static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
841 struct audio_effect_config effect_config,
842 unsigned int param_value)
843{
844 char mixer_ctl_name[] = "Audio Effect";
845 struct mixer_ctl *ctl;
846 long set_values[6];
847 struct stream_in *in = adev->active_input;
848
849 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
850 if (!ctl) {
851 ALOGE("%s: Could not get mixer ctl - %s",
852 __func__, mixer_ctl_name);
853 return -EINVAL;
854 }
855
856 set_values[0] = 1; //0:Rx 1:Tx
857 set_values[1] = in->app_type_cfg.app_type;
858 set_values[2] = (long)effect_config.module_id;
859 set_values[3] = (long)effect_config.instance_id;
860 set_values[4] = (long)effect_config.param_id;
861 set_values[5] = param_value;
862
863 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
864
865 return 0;
866
867}
868
869static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
870 int effect_type, unsigned int *param_value)
871{
872 int ret = 0;
873 struct audio_effect_config other_effect_config;
874 struct audio_usecase *usecase = NULL;
875 struct stream_in *in = adev->active_input;
876
877 usecase = get_usecase_from_list(adev, in->usecase);
878 if (!usecase)
879 return -EINVAL;
880
881 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
882 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
883 if (ret < 0) {
884 ALOGE("%s Failed to get effect params %d", __func__, ret);
885 return ret;
886 }
887
888 if (module_id == other_effect_config.module_id) {
889 //Same module id for AEC/NS. Values need to be combined
890 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
891 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
892 *param_value |= other_effect_config.param_value;
893 }
894 }
895
896 return ret;
897}
898
899static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
900{
901 struct audio_effect_config effect_config;
902 struct audio_usecase *usecase = NULL;
903 int ret = 0;
904 unsigned int param_value = 0;
905 struct stream_in *in = adev->active_input;
906
907 if (!in) {
908 ALOGE("%s: Invalid input stream", __func__);
909 return -EINVAL;
910 }
911
912 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
913
914 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800915 if (usecase == NULL) {
916 ALOGE("%s: Could not find the usecase (%d) in the list",
917 __func__, in->usecase);
918 return -EINVAL;
919 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700920
921 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
922 if (ret < 0) {
923 ALOGE("%s Failed to get module id %d", __func__, ret);
924 return ret;
925 }
926 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
927 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
928
929 if(enable)
930 param_value = effect_config.param_value;
931
932 /*Special handling for AEC & NS effects Param values need to be
933 updated if module ids are same*/
934
935 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
936 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
937 if (ret < 0)
938 return ret;
939 }
940
941 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
942
943 return ret;
944}
945
946static void check_and_enable_effect(struct audio_device *adev)
947{
948
949 if (adev->active_input->enable_aec) {
950 enable_disable_effect(adev, EFFECT_AEC, true);
951 }
952
953 if (adev->active_input->enable_ns &&
954 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
955 enable_disable_effect(adev, EFFECT_NS, true);
956 }
957}
958#else
959#define enable_disable_effect(x, y, z) ENOSYS
960#define check_and_enable_effect(x) ENOSYS
961#endif
962
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700963int pcm_ioctl(struct pcm *pcm, int request, ...)
964{
965 va_list ap;
966 void * arg;
967 int pcm_fd = *(int*)pcm;
968
969 va_start(ap, request);
970 arg = va_arg(ap, void *);
971 va_end(ap);
972
973 return ioctl(pcm_fd, request, arg);
974}
975
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700976int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700977 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800978{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700980 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530981 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800982
983 if (usecase == NULL)
984 return -EINVAL;
985
986 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
987
Surendar Karka93cd25a2018-08-28 14:21:37 +0530988 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700989 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800990 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700991 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800992
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800993#ifdef DS1_DOLBY_DAP_ENABLED
994 audio_extn_dolby_set_dmid(adev);
995 audio_extn_dolby_set_endpoint(adev);
996#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700997 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700998 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530999 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001000 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301001 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301002 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1003 out = usecase->stream.out;
1004 if (out && out->compr)
1005 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1006 }
1007
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001008 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001009 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001010 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001011 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001012 ALOGV("%s: exit", __func__);
1013 return 0;
1014}
1015
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001016int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001017 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001019 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001020 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001021
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301022 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001023 return -EINVAL;
1024
1025 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301026 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001027 snd_device = usecase->in_snd_device;
1028 else
1029 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001030 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001031 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001032 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001033 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001034 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301035 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001036 ALOGV("%s: exit", __func__);
1037 return 0;
1038}
1039
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001040int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001041 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001042{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301043 int i, num_devices = 0;
1044 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001045 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1046
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001047 if (snd_device < SND_DEVICE_MIN ||
1048 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001049 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001050 return -EINVAL;
1051 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001052
1053 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001054
1055 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
1056 ALOGE("%s: Invalid sound device returned", __func__);
1057 return -EINVAL;
1058 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001059 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -07001060 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001061 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001062 return 0;
1063 }
1064
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301065
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001066 if (audio_extn_spkr_prot_is_enabled())
1067 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001068
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001069 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1070 audio_extn_spkr_prot_is_enabled()) {
1071 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001072 adev->snd_dev_ref_cnt[snd_device]--;
1073 return -EINVAL;
1074 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001075 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001076 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001077 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001078 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001079 return -EINVAL;
1080 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001081 } else if (platform_split_snd_device(adev->platform,
1082 snd_device,
1083 &num_devices,
1084 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301085 for (i = 0; i < num_devices; i++) {
1086 enable_snd_device(adev, new_snd_devices[i]);
1087 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001088 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001089 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301090
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301091
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301092 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1093 (audio_extn_a2dp_start_playback() < 0)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02001094 ALOGE(" fail to configure A2dp Source control path ");
1095 return -EINVAL;
1096 }
1097
1098 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1099 (audio_extn_a2dp_start_capture() < 0)) {
1100 ALOGE(" fail to configure A2dp Sink control path ");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301101 return -EINVAL;
1102 }
1103
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001104 /* due to the possibility of calibration overwrite between listen
1105 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001106 audio_extn_sound_trigger_update_device_status(snd_device,
1107 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301108 audio_extn_listen_update_device_status(snd_device,
1109 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001110 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001111 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001112 audio_extn_sound_trigger_update_device_status(snd_device,
1113 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301114 audio_extn_listen_update_device_status(snd_device,
1115 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001116 return -EINVAL;
1117 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001118 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001119 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301120
1121 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1122 !adev->native_playback_enabled &&
1123 audio_is_true_native_stream_active(adev)) {
1124 ALOGD("%s: %d: napb: enabling native mode in hardware",
1125 __func__, __LINE__);
1126 audio_route_apply_and_update_path(adev->audio_route,
1127 "true-native-mode");
1128 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301129 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301130 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1131 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001132 (audio_extn_ffv_get_stream() == adev->active_input)) {
1133 ALOGD("%s: init ec ref loopback", __func__);
1134 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1135 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001136 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001137 return 0;
1138}
1139
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001140int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001141 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001142{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301143 int i, num_devices = 0;
1144 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001145 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1146
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001147 if (snd_device < SND_DEVICE_MIN ||
1148 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001149 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001150 return -EINVAL;
1151 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1153 ALOGE("%s: device ref cnt is already 0", __func__);
1154 return -EINVAL;
1155 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001156
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001157 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001158
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001159 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1160 ALOGE("%s: Invalid sound device returned", __func__);
1161 return -EINVAL;
1162 }
1163
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001164 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001165 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301166
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001167 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1168 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001169 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001170
1171 // when speaker device is disabled, reset swap.
1172 // will be renabled on usecase start
1173 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001174 } else if (platform_split_snd_device(adev->platform,
1175 snd_device,
1176 &num_devices,
1177 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301178 for (i = 0; i < num_devices; i++) {
1179 disable_snd_device(adev, new_snd_devices[i]);
1180 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001181 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001182 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001183 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001184
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301185 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1186 audio_extn_a2dp_stop_playback();
1187
Florian Pfister1a84f312018-07-19 14:38:18 +02001188 if (SND_DEVICE_IN_BT_A2DP == snd_device)
1189 audio_extn_a2dp_stop_capture();
1190
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001191 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301192 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301193 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1194 adev->native_playback_enabled) {
1195 ALOGD("%s: %d: napb: disabling native mode in hardware",
1196 __func__, __LINE__);
1197 audio_route_reset_and_update_path(adev->audio_route,
1198 "true-native-mode");
1199 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301200 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1201 adev->asrc_mode_enabled) {
1202 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301203 disable_asrc_mode(adev);
1204 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301205 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001206 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1207 (audio_extn_ffv_get_stream() == adev->active_input)) {
1208 ALOGD("%s: deinit ec ref loopback", __func__);
1209 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1210 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001211 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001212 audio_extn_sound_trigger_update_device_status(snd_device,
1213 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301214 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001215 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001216 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001218 return 0;
1219}
1220
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001221/*
1222 legend:
1223 uc - existing usecase
1224 new_uc - new usecase
1225 d1, d11, d2 - SND_DEVICE enums
1226 a1, a2 - corresponding ANDROID device enums
1227 B1, B2 - backend strings
1228
1229case 1
1230 uc->dev d1 (a1) B1
1231 new_uc->dev d1 (a1), d2 (a2) B1, B2
1232
1233 resolution: disable and enable uc->dev on d1
1234
1235case 2
1236 uc->dev d1 (a1) B1
1237 new_uc->dev d11 (a1) B1
1238
1239 resolution: need to switch uc since d1 and d11 are related
1240 (e.g. speaker and voice-speaker)
1241 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1242
1243case 3
1244 uc->dev d1 (a1) B1
1245 new_uc->dev d2 (a2) B2
1246
1247 resolution: no need to switch uc
1248
1249case 4
1250 uc->dev d1 (a1) B1
1251 new_uc->dev d2 (a2) B1
1252
1253 resolution: disable enable uc-dev on d2 since backends match
1254 we cannot enable two streams on two different devices if they
1255 share the same backend. e.g. if offload is on speaker device using
1256 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1257 using the same backend, offload must also be switched to voice-handset.
1258
1259case 5
1260 uc->dev d1 (a1) B1
1261 new_uc->dev d1 (a1), d2 (a2) B1
1262
1263 resolution: disable enable uc-dev on d2 since backends match
1264 we cannot enable two streams on two different devices if they
1265 share the same backend.
1266
1267case 6
1268 uc->dev d1 (a1) B1
1269 new_uc->dev d2 (a1) B2
1270
1271 resolution: no need to switch
1272
1273case 7
1274 uc->dev d1 (a1), d2 (a2) B1, B2
1275 new_uc->dev d1 (a1) B1
1276
1277 resolution: no need to switch
1278
Zhou Song4ba65882018-07-09 14:48:07 +08001279case 8
1280 uc->dev d1 (a1) B1
1281 new_uc->dev d11 (a1), d2 (a2) B1, B2
1282 resolution: compared to case 1, for this case, d1 and d11 are related
1283 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001284*/
1285static snd_device_t derive_playback_snd_device(void * platform,
1286 struct audio_usecase *uc,
1287 struct audio_usecase *new_uc,
1288 snd_device_t new_snd_device)
1289{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301290 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001291
1292 snd_device_t d1 = uc->out_snd_device;
1293 snd_device_t d2 = new_snd_device;
1294
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301295 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301296 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301297 a1 = uc->stream.inout->out_config.devices;
1298 a2 = new_uc->stream.inout->out_config.devices;
1299 break;
1300 default :
1301 a1 = uc->stream.out->devices;
1302 a2 = new_uc->stream.out->devices;
1303 break;
1304 }
1305
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001306 // Treat as a special case when a1 and a2 are not disjoint
1307 if ((a1 != a2) && (a1 & a2)) {
1308 snd_device_t d3[2];
1309 int num_devices = 0;
1310 int ret = platform_split_snd_device(platform,
1311 popcount(a1) > 1 ? d1 : d2,
1312 &num_devices,
1313 d3);
1314 if (ret < 0) {
1315 if (ret != -ENOSYS) {
1316 ALOGW("%s failed to split snd_device %d",
1317 __func__,
1318 popcount(a1) > 1 ? d1 : d2);
1319 }
1320 goto end;
1321 }
1322
1323 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1324 // But if it does happen, we need to give priority to d2 if
1325 // the combo devices active on the existing usecase share a backend.
1326 // This is because we cannot have a usecase active on a combo device
1327 // and a new usecase requests one device in this combo pair.
1328 if (platform_check_backends_match(d3[0], d3[1])) {
1329 return d2; // case 5
1330 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001331 // check if d1 is related to any of d3's
1332 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001333 return d1; // case 1
1334 else
1335 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001336 }
1337 } else {
1338 if (platform_check_backends_match(d1, d2)) {
1339 return d2; // case 2, 4
1340 } else {
1341 return d1; // case 6, 3
1342 }
1343 }
1344
1345end:
1346 return d2; // return whatever was calculated before.
1347}
1348
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001349static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301350 struct audio_usecase *uc_info,
1351 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001352{
1353 struct listnode *node;
1354 struct audio_usecase *usecase;
1355 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301356 snd_device_t uc_derive_snd_device;
1357 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001358 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001359 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301360 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001361 /*
1362 * This function is to make sure that all the usecases that are active on
1363 * the hardware codec backend are always routed to any one device that is
1364 * handled by the hardware codec.
1365 * For example, if low-latency and deep-buffer usecases are currently active
1366 * on speaker and out_set_parameters(headset) is received on low-latency
1367 * output, then we have to make sure deep-buffer is also switched to headset,
1368 * because of the limitation that both the devices cannot be enabled
1369 * at the same time as they share the same backend.
1370 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001371 /*
1372 * This call is to check if we need to force routing for a particular stream
1373 * If there is a backend configuration change for the device when a
1374 * new stream starts, then ADM needs to be closed and re-opened with the new
1375 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001376 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001377 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001378 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1379 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301380 /* For a2dp device reconfigure all active sessions
1381 * with new AFE encoder format based on a2dp state
1382 */
1383 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1384 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1385 audio_extn_a2dp_is_force_device_switch()) {
1386 force_routing = true;
1387 force_restart_session = true;
1388 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301389 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1390
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001391 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001392 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001393 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001394 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1395 switch_device[i] = false;
1396
1397 list_for_each(node, &adev->usecase_list) {
1398 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001399
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301400 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1401 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301402 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301403 platform_get_snd_device_name(usecase->out_snd_device),
1404 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301405 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1406 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1407 usecase, uc_info, snd_device);
1408 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1409 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1410 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1411 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001412 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301413 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1414 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1415 ((force_restart_session) ||
1416 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301417 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1418 __func__, use_case_table[usecase->id],
1419 platform_get_snd_device_name(usecase->out_snd_device));
1420 disable_audio_route(adev, usecase);
1421 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301422 /* Enable existing usecase on derived playback device */
1423 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301424 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301425 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001426 }
1427 }
1428
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301429 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1430 num_uc_to_switch);
1431
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001432 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001433 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001434
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301435 /* Make sure the previous devices to be disabled first and then enable the
1436 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001437 list_for_each(node, &adev->usecase_list) {
1438 usecase = node_to_item(node, struct audio_usecase, list);
1439 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001440 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001441 }
1442 }
1443
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001444 list_for_each(node, &adev->usecase_list) {
1445 usecase = node_to_item(node, struct audio_usecase, list);
1446 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301447 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001448 }
1449 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001450
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001451 /* Re-route all the usecases on the shared backend other than the
1452 specified usecase to new snd devices */
1453 list_for_each(node, &adev->usecase_list) {
1454 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301455 /* Update the out_snd_device only before enabling the audio route */
1456 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301457 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301458 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301459 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301460 use_case_table[usecase->id],
1461 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001462 /* Update voc calibration before enabling VoIP route */
1463 if (usecase->type == VOIP_CALL)
1464 status = platform_switch_voice_call_device_post(adev->platform,
1465 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001466 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301467 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001468 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1469 out_set_voip_volume(&usecase->stream.out->stream,
1470 usecase->stream.out->volume_l,
1471 usecase->stream.out->volume_r);
1472 }
Yidong Huang7939a3b2018-01-23 17:32:30 +08001473 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1474 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1475 if (parms)
1476 audio_extn_fm_set_parameters(adev, parms);
1477 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301478 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001479 }
1480 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001481 }
1482}
1483
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301484static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001485 struct audio_usecase *uc_info,
1486 snd_device_t snd_device)
1487{
1488 struct listnode *node;
1489 struct audio_usecase *usecase;
1490 bool switch_device[AUDIO_USECASE_MAX];
1491 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301492 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001493 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001494
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301495 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1496 snd_device);
1497 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301498
1499 /*
1500 * Make sure out devices is checked against out codec backend device and
1501 * also in devices against in codec backend. Checking out device against in
1502 * codec backend or vice versa causes issues.
1503 */
1504 if (uc_info->type == PCM_CAPTURE)
1505 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001506 /*
1507 * This function is to make sure that all the active capture usecases
1508 * are always routed to the same input sound device.
1509 * For example, if audio-record and voice-call usecases are currently
1510 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1511 * is received for voice call then we have to make sure that audio-record
1512 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1513 * because of the limitation that two devices cannot be enabled
1514 * at the same time if they share the same backend.
1515 */
1516 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1517 switch_device[i] = false;
1518
1519 list_for_each(node, &adev->usecase_list) {
1520 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301521 /*
1522 * TODO: Enhance below condition to handle BT sco/USB multi recording
1523 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001524 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001525 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301526 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301527 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301528 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301529 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001530 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001531 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1532 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001533 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001534 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001535 switch_device[usecase->id] = true;
1536 num_uc_to_switch++;
1537 }
1538 }
1539
1540 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001541 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001542
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301543 /* Make sure the previous devices to be disabled first and then enable the
1544 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001545 list_for_each(node, &adev->usecase_list) {
1546 usecase = node_to_item(node, struct audio_usecase, list);
1547 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001548 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001549 }
1550 }
1551
1552 list_for_each(node, &adev->usecase_list) {
1553 usecase = node_to_item(node, struct audio_usecase, list);
1554 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001555 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001556 }
1557 }
1558
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001559 /* Re-route all the usecases on the shared backend other than the
1560 specified usecase to new snd devices */
1561 list_for_each(node, &adev->usecase_list) {
1562 usecase = node_to_item(node, struct audio_usecase, list);
1563 /* Update the in_snd_device only before enabling the audio route */
1564 if (switch_device[usecase->id] ) {
1565 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001566 if (usecase->type != VOICE_CALL) {
1567 /* Update voc calibration before enabling VoIP route */
1568 if (usecase->type == VOIP_CALL)
1569 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001570 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001571 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301572 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001573 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001574 }
1575 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001576 }
1577}
1578
Mingming Yin3a941d42016-02-17 18:08:05 -08001579static void reset_hdmi_sink_caps(struct stream_out *out) {
1580 int i = 0;
1581
1582 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1583 out->supported_channel_masks[i] = 0;
1584 }
1585 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1586 out->supported_formats[i] = 0;
1587 }
1588 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1589 out->supported_sample_rates[i] = 0;
1590 }
1591}
1592
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001593/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001594static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001595{
Mingming Yin3a941d42016-02-17 18:08:05 -08001596 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001597 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001598
Mingming Yin3a941d42016-02-17 18:08:05 -08001599 reset_hdmi_sink_caps(out);
1600
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001601 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001602 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001603 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001604 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001605 }
1606
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001607 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001608 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001609 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001610 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001611 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1612 case 6:
1613 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1614 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1615 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1616 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1617 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1618 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001619 break;
1620 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001621 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001622 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001623 break;
1624 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001625
1626 // check channel format caps
1627 i = 0;
1628 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1629 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1630 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1631 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1632 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1633 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1634 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1635 }
1636
Ben Romberger1aaaf862017-04-06 17:49:46 -07001637 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1638 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1639 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1640 }
1641
Mingming Yin3a941d42016-02-17 18:08:05 -08001642 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1643 ALOGV(":%s HDMI supports DTS format", __func__);
1644 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1645 }
1646
1647 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1648 ALOGV(":%s HDMI supports DTS HD format", __func__);
1649 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1650 }
1651
Naresh Tanniru928f0862017-04-07 16:44:23 -07001652 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1653 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1654 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1655 }
1656
Mingming Yin3a941d42016-02-17 18:08:05 -08001657
1658 // check sample rate caps
1659 i = 0;
1660 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1661 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1662 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1663 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1664 }
1665 }
1666
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001667 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001668}
1669
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001670static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1671 uint32_t *supported_sample_rates __unused,
1672 uint32_t max_rates __unused)
1673{
1674 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1675 supported_sample_rates,
1676 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301677 ssize_t i = 0;
1678
1679 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001680 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1681 supported_sample_rates[i]);
1682 }
1683 return count;
1684}
1685
1686static inline int read_usb_sup_channel_masks(bool is_playback,
1687 audio_channel_mask_t *supported_channel_masks,
1688 uint32_t max_masks)
1689{
1690 int channels = audio_extn_usb_get_max_channels(is_playback);
1691 int channel_count;
1692 uint32_t num_masks = 0;
1693 if (channels > MAX_HIFI_CHANNEL_COUNT)
1694 channels = MAX_HIFI_CHANNEL_COUNT;
1695
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301696 channel_count = DEFAULT_CHANNEL_COUNT;
1697
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001698 if (is_playback) {
1699 // For playback we never report mono because the framework always outputs stereo
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001700 // audio_channel_out_mask_from_count() does return positional masks for channel counts
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301701 // above 2 but we want indexed masks here.
1702 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001703 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001704 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1705 // indexed mask
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301706 supported_channel_masks[num_masks++] = audio_channel_in_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001707 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301708
1709 for (channel_count = channels; ((channel_count >= DEFAULT_CHANNEL_COUNT) &&
1710 (num_masks < max_masks)); channel_count--) {
1711 supported_channel_masks[num_masks++] =
1712 audio_channel_mask_for_index_assignment_from_count(channel_count);
1713 }
1714
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001715 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1716 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1717 return num_masks;
1718}
1719
1720static inline int read_usb_sup_formats(bool is_playback __unused,
1721 audio_format_t *supported_formats,
1722 uint32_t max_formats __unused)
1723{
1724 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1725 switch (bitwidth) {
1726 case 24:
1727 // XXX : usb.c returns 24 for s24 and s24_le?
1728 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1729 break;
1730 case 32:
1731 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1732 break;
1733 case 16:
1734 default :
1735 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1736 break;
1737 }
1738 ALOGV("%s: %s supported format %d", __func__,
1739 is_playback ? "P" : "C", bitwidth);
1740 return 1;
1741}
1742
1743static inline int read_usb_sup_params_and_compare(bool is_playback,
1744 audio_format_t *format,
1745 audio_format_t *supported_formats,
1746 uint32_t max_formats,
1747 audio_channel_mask_t *mask,
1748 audio_channel_mask_t *supported_channel_masks,
1749 uint32_t max_masks,
1750 uint32_t *rate,
1751 uint32_t *supported_sample_rates,
1752 uint32_t max_rates) {
1753 int ret = 0;
1754 int num_formats;
1755 int num_masks;
1756 int num_rates;
1757 int i;
1758
1759 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1760 max_formats);
1761 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1762 max_masks);
1763
1764 num_rates = read_usb_sup_sample_rates(is_playback,
1765 supported_sample_rates, max_rates);
1766
1767#define LUT(table, len, what, dflt) \
1768 for (i=0; i<len && (table[i] != what); i++); \
1769 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1770
1771 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1772 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1773 LUT(supported_sample_rates, num_rates, *rate, 0);
1774
1775#undef LUT
1776 return ret < 0 ? -EINVAL : 0; // HACK TBD
1777}
1778
Alexy Josephb1379942016-01-29 15:49:38 -08001779audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001780 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001781{
1782 struct audio_usecase *usecase;
1783 struct listnode *node;
1784
1785 list_for_each(node, &adev->usecase_list) {
1786 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001787 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001788 ALOGV("%s: usecase id %d", __func__, usecase->id);
1789 return usecase->id;
1790 }
1791 }
1792 return USECASE_INVALID;
1793}
1794
Alexy Josephb1379942016-01-29 15:49:38 -08001795struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001796 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001797{
1798 struct audio_usecase *usecase;
1799 struct listnode *node;
1800
1801 list_for_each(node, &adev->usecase_list) {
1802 usecase = node_to_item(node, struct audio_usecase, list);
1803 if (usecase->id == uc_id)
1804 return usecase;
1805 }
1806 return NULL;
1807}
1808
Dhananjay Kumard4833242016-10-06 22:09:12 +05301809struct stream_in *get_next_active_input(const struct audio_device *adev)
1810{
1811 struct audio_usecase *usecase;
1812 struct listnode *node;
1813
1814 list_for_each_reverse(node, &adev->usecase_list) {
1815 usecase = node_to_item(node, struct audio_usecase, list);
1816 if (usecase->type == PCM_CAPTURE)
1817 return usecase->stream.in;
1818 }
1819 return NULL;
1820}
1821
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301822/*
1823 * is a true native playback active
1824 */
1825bool audio_is_true_native_stream_active(struct audio_device *adev)
1826{
1827 bool active = false;
1828 int i = 0;
1829 struct listnode *node;
1830
1831 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1832 ALOGV("%s:napb: not in true mode or non hdphones device",
1833 __func__);
1834 active = false;
1835 goto exit;
1836 }
1837
1838 list_for_each(node, &adev->usecase_list) {
1839 struct audio_usecase *uc;
1840 uc = node_to_item(node, struct audio_usecase, list);
1841 struct stream_out *curr_out =
1842 (struct stream_out*) uc->stream.out;
1843
1844 if (curr_out && PCM_PLAYBACK == uc->type) {
1845 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1846 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1847 uc->id, curr_out->sample_rate,
1848 curr_out->bit_width,
1849 platform_get_snd_device_name(uc->out_snd_device));
1850
1851 if (is_offload_usecase(uc->id) &&
1852 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1853 active = true;
1854 ALOGD("%s:napb:native stream detected", __func__);
1855 }
1856 }
1857 }
1858exit:
1859 return active;
1860}
1861
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001862uint32_t adev_get_dsp_bit_width_enforce_mode()
1863{
1864 if (adev == NULL) {
1865 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1866 return 0;
1867 }
1868 return adev->dsp_bit_width_enforce_mode;
1869}
1870
1871static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1872{
1873 char value[PROPERTY_VALUE_MAX];
1874 int trial;
1875 uint32_t dsp_bit_width_enforce_mode = 0;
1876
1877 if (!mixer) {
1878 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1879 __func__);
1880 return 0;
1881 }
1882
1883 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1884 value, NULL) > 0) {
1885 trial = atoi(value);
1886 switch (trial) {
1887 case 16:
1888 dsp_bit_width_enforce_mode = 16;
1889 break;
1890 case 24:
1891 dsp_bit_width_enforce_mode = 24;
1892 break;
1893 case 32:
1894 dsp_bit_width_enforce_mode = 32;
1895 break;
1896 default:
1897 dsp_bit_width_enforce_mode = 0;
1898 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1899 break;
1900 }
1901 }
1902
1903 return dsp_bit_width_enforce_mode;
1904}
1905
1906static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1907 uint32_t enforce_mode,
1908 bool enable)
1909{
1910 struct mixer_ctl *ctl = NULL;
1911 const char *mixer_ctl_name = "ASM Bit Width";
1912 uint32_t asm_bit_width_mode = 0;
1913
1914 if (enforce_mode == 0) {
1915 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1916 return;
1917 }
1918
1919 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1920 if (!ctl) {
1921 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1922 __func__, mixer_ctl_name);
1923 return;
1924 }
1925
1926 if (enable)
1927 asm_bit_width_mode = enforce_mode;
1928 else
1929 asm_bit_width_mode = 0;
1930
1931 ALOGV("%s DSP bit width feature status is %d width=%d",
1932 __func__, enable, asm_bit_width_mode);
1933 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1934 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1935 asm_bit_width_mode);
1936
1937 return;
1938}
1939
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301940/*
1941 * if native DSD playback active
1942 */
1943bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1944{
1945 bool active = false;
1946 struct listnode *node = NULL;
1947 struct audio_usecase *uc = NULL;
1948 struct stream_out *curr_out = NULL;
1949
1950 list_for_each(node, &adev->usecase_list) {
1951 uc = node_to_item(node, struct audio_usecase, list);
1952 curr_out = (struct stream_out*) uc->stream.out;
1953
1954 if (curr_out && PCM_PLAYBACK == uc->type &&
1955 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1956 active = true;
1957 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301958 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301959 }
1960 }
1961 return active;
1962}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301963
1964static bool force_device_switch(struct audio_usecase *usecase)
1965{
1966 bool ret = false;
1967 bool is_it_true_mode = false;
1968
Zhou Song30f2c3e2018-02-08 14:02:15 +08001969 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05301970 usecase->type == TRANSCODE_LOOPBACK_RX ||
1971 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08001972 return false;
1973 }
1974
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001975 if(usecase->stream.out == NULL) {
1976 ALOGE("%s: stream.out is NULL", __func__);
1977 return false;
1978 }
1979
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301980 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001981 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1982 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1983 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301984 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1985 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1986 (!is_it_true_mode && adev->native_playback_enabled)){
1987 ret = true;
1988 ALOGD("napb: time to toggle native mode");
1989 }
1990 }
1991
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301992 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301993 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1994 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001995 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301996 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301997 ALOGD("Force a2dp device switch to update new encoder config");
1998 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02001999 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302000
Florian Pfister1a84f312018-07-19 14:38:18 +02002001 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302002 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2003 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002004 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302005 return ret;
2006}
2007
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302008bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2009{
2010 bool ret=false;
2011 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2012 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2013 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2014 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2015 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2016 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2017 ret = true;
2018
2019 return ret;
2020}
2021
2022bool is_a2dp_device(snd_device_t out_snd_device)
2023{
2024 bool ret=false;
2025 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2026 ret = true;
2027
2028 return ret;
2029}
2030
2031bool is_bt_soc_on(struct audio_device *adev)
2032{
2033 struct mixer_ctl *ctl;
2034 char *mixer_ctl_name = "BT SOC status";
2035 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2036 bool bt_soc_status = true;
2037 if (!ctl) {
2038 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2039 __func__, mixer_ctl_name);
2040 /*This is to ensure we dont break targets which dont have the kernel change*/
2041 return true;
2042 }
2043 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2044 ALOGD("BT SOC status: %d",bt_soc_status);
2045 return bt_soc_status;
2046}
2047
2048int out_standby_l(struct audio_stream *stream);
2049
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002050int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002051{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002052 snd_device_t out_snd_device = SND_DEVICE_NONE;
2053 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002054 struct audio_usecase *usecase = NULL;
2055 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002056 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002057 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302058 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002059 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002060 int status = 0;
Jhansi Konathala902fc412018-09-05 13:21:44 +05302061 audio_devices_t audio_device = AUDIO_DEVICE_NONE;
2062 audio_channel_mask_t channel_mask = AUDIO_CHANNEL_NONE;
2063 int sample_rate = 0;
2064 int acdb_id = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302066 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2067
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002068 usecase = get_usecase_from_list(adev, uc_id);
2069 if (usecase == NULL) {
2070 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2071 return -EINVAL;
2072 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002073
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002074 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002075 (usecase->type == VOIP_CALL) ||
2076 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302077 if(usecase->stream.out == NULL) {
2078 ALOGE("%s: stream.out is NULL", __func__);
2079 return -EINVAL;
2080 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002081 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002082 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002083 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002084 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302085 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302086 if (usecase->stream.inout == NULL) {
2087 ALOGE("%s: stream.inout is NULL", __func__);
2088 return -EINVAL;
2089 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302090 stream_out.devices = usecase->stream.inout->out_config.devices;
2091 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2092 stream_out.format = usecase->stream.inout->out_config.format;
2093 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2094 out_snd_device = platform_get_output_snd_device(adev->platform,
2095 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302096 usecase->devices = out_snd_device;
2097 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2098 if (usecase->stream.inout == NULL) {
2099 ALOGE("%s: stream.inout is NULL", __func__);
2100 return -EINVAL;
2101 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302102 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302103 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002104 } else {
2105 /*
2106 * If the voice call is active, use the sound devices of voice call usecase
2107 * so that it would not result any device switch. All the usecases will
2108 * be switched to new device when select_devices() is called for voice call
2109 * usecase. This is to avoid switching devices for voice call when
2110 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002111 * choose voice call device only if the use case device is
2112 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002113 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002114 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002115 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002116 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002117 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2118 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302119 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2120 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002121 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002122 in_snd_device = vc_usecase->in_snd_device;
2123 out_snd_device = vc_usecase->out_snd_device;
2124 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002125 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002126 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002127 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002128 if ((voip_usecase != NULL) &&
2129 (usecase->type == PCM_PLAYBACK) &&
2130 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002131 out_snd_device_backend_match = platform_check_backends_match(
2132 voip_usecase->out_snd_device,
2133 platform_get_output_snd_device(
2134 adev->platform,
2135 usecase->stream.out));
2136 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002137 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002138 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2139 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002140 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002141 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002142 in_snd_device = voip_usecase->in_snd_device;
2143 out_snd_device = voip_usecase->out_snd_device;
2144 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002145 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002146 hfp_ucid = audio_extn_hfp_get_usecase();
2147 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002148 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002149 in_snd_device = hfp_usecase->in_snd_device;
2150 out_snd_device = hfp_usecase->out_snd_device;
2151 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002152 }
2153 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302154 if (usecase->stream.out == NULL) {
2155 ALOGE("%s: stream.out is NULL", __func__);
2156 return -EINVAL;
2157 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002158 usecase->devices = usecase->stream.out->devices;
2159 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002160 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002161 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002162 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002163 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizb27e7952018-10-12 15:49:35 +08002164 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002165 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2166
2167 if ((usecase->stream.out != NULL &&
2168 voip_usecase != NULL &&
2169 usecase->stream.out->usecase == voip_usecase->id) &&
2170 adev->active_input &&
kunleizb27e7952018-10-12 15:49:35 +08002171 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002172 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002173 select_devices(adev, adev->active_input->usecase);
2174 }
2175 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002176 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302177 if (usecase->stream.in == NULL) {
2178 ALOGE("%s: stream.in is NULL", __func__);
2179 return -EINVAL;
2180 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002181 usecase->devices = usecase->stream.in->device;
2182 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002183 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002184 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002185 if (adev->active_input &&
2186 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302187 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002188 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2189 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2190 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2191 out_device = voip_usecase->stream.out->devices;
2192 else if (adev->primary_output && !adev->primary_output->standby)
2193 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002194 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002195 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2196 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002197 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002198 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002199 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002200 }
2201 }
2202
2203 if (out_snd_device == usecase->out_snd_device &&
2204 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302205
2206 if (!force_device_switch(usecase))
2207 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208 }
2209
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302210 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002211 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302212 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2213 return 0;
2214 }
2215
sangwoobc677242013-08-08 16:53:43 +09002216 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07002217 out_snd_device, platform_get_snd_device_name(out_snd_device),
2218 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002219
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220 /*
2221 * Limitation: While in call, to do a device switch we need to disable
2222 * and enable both RX and TX devices though one of them is same as current
2223 * device.
2224 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002225 if ((usecase->type == VOICE_CALL) &&
2226 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2227 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002228 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002229 }
2230
2231 if (((usecase->type == VOICE_CALL) ||
2232 (usecase->type == VOIP_CALL)) &&
2233 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2234 /* Disable sidetone only if voice/voip call already exists */
2235 if (voice_is_call_state_active(adev) ||
2236 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002237 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002238
2239 /* Disable aanc only if voice call exists */
2240 if (voice_is_call_state_active(adev))
2241 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002242 }
2243
Zhou Songc66eb7e2017-08-08 18:29:07 +08002244 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002245 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302246 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002247 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302248 }
2249
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002250 /* Disable current sound devices */
2251 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002252 disable_audio_route(adev, usecase);
2253 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 }
2255
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002256 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002257 disable_audio_route(adev, usecase);
2258 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259 }
2260
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002261 /* Applicable only on the targets that has external modem.
2262 * New device information should be sent to modem before enabling
2263 * the devices to reduce in-call device switch time.
2264 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002265 if ((usecase->type == VOICE_CALL) &&
2266 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2267 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002268 status = platform_switch_voice_call_enable_device_config(adev->platform,
2269 out_snd_device,
2270 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002271 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002272
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002273 /* Enable new sound devices */
2274 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002275 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302276 if (platform_check_codec_asrc_support(adev->platform))
2277 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002278 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279 }
2280
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002281 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302282 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002283 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002284 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002285
Avinash Vaish71a8b972014-07-24 15:36:33 +05302286 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002287 status = platform_switch_voice_call_device_post(adev->platform,
2288 out_snd_device,
2289 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302290 enable_audio_route_for_voice_usecases(adev, usecase);
2291 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002292
sangwoo170731f2013-06-08 15:36:36 +09002293 usecase->in_snd_device = in_snd_device;
2294 usecase->out_snd_device = out_snd_device;
2295
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302296 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2297 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302298 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002299 if ((24 == usecase->stream.out->bit_width) &&
2300 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2301 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2302 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2303 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2304 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2305 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2306 /*
2307 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2308 * configured device sample rate, if not update the COPP rate to be equal to the
2309 * device sample rate, else open COPP at stream sample rate
2310 */
2311 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2312 usecase->stream.out->sample_rate,
2313 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302314 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2315 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002316 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2317 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2318 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2319 }
2320
Weiyin Jiang5d608082018-02-01 17:24:33 +08002321 /* Cache stream information to be notified to gef clients */
2322 audio_device = usecase->stream.out->devices;
2323 channel_mask = usecase->stream.out->channel_mask;
2324 sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
2325 acdb_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302326 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002327 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002328
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002329 /* If input stream is already running then effect needs to be
2330 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002331 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2332 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002333 check_and_enable_effect(adev);
2334
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002335 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002336 /* Enable aanc only if voice call exists */
2337 if (voice_is_call_state_active(adev))
2338 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2339
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002340 /* Enable sidetone only if other voice/voip call already exists */
2341 if (voice_is_call_state_active(adev) ||
2342 voice_extn_compress_voip_is_started(adev))
2343 voice_set_sidetone(adev, out_snd_device, true);
2344 }
2345
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002346 /* Applicable only on the targets that has external modem.
2347 * Enable device command should be sent to modem only after
2348 * enabling voice call mixer controls
2349 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002350 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002351 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2352 out_snd_device,
2353 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302354
2355 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2356
2357 if (usecase->type == VOIP_CALL) {
2358 if (adev->active_input != NULL &&
2359 !adev->active_input->standby) {
2360 if (is_bt_soc_on(adev) == false){
2361 ALOGD("BT SCO MIC disconnected while in connection");
2362 if (adev->active_input->pcm != NULL)
2363 pcm_stop(adev->active_input->pcm);
2364 }
2365 }
2366 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2367 && usecase->stream.out->started) {
2368 if (is_bt_soc_on(adev) == false) {
2369 ALOGD("BT SCO/A2DP disconnected while in connection");
2370 out_standby_l(&usecase->stream.out->stream.common);
2371 }
2372 }
2373 } else if ((usecase->stream.out != NULL) &&
2374 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302375 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2376 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302377 usecase->stream.out->started) {
2378 if (is_bt_soc_on(adev) == false) {
2379 ALOGD("BT SCO/A2dp disconnected while in connection");
2380 out_standby_l(&usecase->stream.out->stream.common);
2381 }
2382 }
2383 }
2384
Weiyin Jiang5d608082018-02-01 17:24:33 +08002385 /* Notify device change info to effect clients registered
2386 * NOTE: device lock has to be unlock temporarily here.
2387 * To the worst case, we notify stale info to clients.
2388 */
2389 if (usecase->type == PCM_PLAYBACK) {
2390 pthread_mutex_unlock(&adev->lock);
2391 audio_extn_gef_notify_device_config(audio_device, channel_mask, sample_rate, acdb_id);
2392 pthread_mutex_lock(&adev->lock);
2393 }
2394
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302395 ALOGD("%s: done",__func__);
2396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002397 return status;
2398}
2399
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002400static int stop_input_stream(struct stream_in *in)
2401{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302402 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002403 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302404
2405 if (in == NULL) {
2406 ALOGE("%s: stream_in ptr is NULL", __func__);
2407 return -EINVAL;
2408 }
2409
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002410 struct audio_device *adev = in->dev;
2411
Eric Laurent994a6932013-07-17 11:51:42 -07002412 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002413 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002414 uc_info = get_usecase_from_list(adev, in->usecase);
2415 if (uc_info == NULL) {
2416 ALOGE("%s: Could not find the usecase (%d) in the list",
2417 __func__, in->usecase);
2418 return -EINVAL;
2419 }
2420
Derek Chend2530072014-11-24 12:39:14 -08002421 if (uc_info->in_snd_device != SND_DEVICE_NONE) {
2422 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2423 ALOGE("%s: failed to stop ext hw plugin", __func__);
2424 }
2425
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002426 /* Close in-call recording streams */
2427 voice_check_and_stop_incall_rec_usecase(adev, in);
2428
Eric Laurent150dbfe2013-02-27 14:31:02 -08002429 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002430 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002431
2432 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002433 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002434
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002435 list_remove(&uc_info->list);
2436 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002438 adev->active_input = get_next_active_input(adev);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302439 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002440 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441 return ret;
2442}
2443
2444int start_input_stream(struct stream_in *in)
2445{
2446 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002447 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002448 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302449
2450 if (in == NULL) {
2451 ALOGE("%s: stream_in ptr is NULL", __func__);
2452 return -EINVAL;
2453 }
2454
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002456 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002457 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002458
Mingming Yin2664a5b2015-09-03 10:53:11 -07002459 if (get_usecase_from_list(adev, usecase) == NULL)
2460 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302461 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2462 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002463
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302464 if (CARD_STATUS_OFFLINE == in->card_status||
2465 CARD_STATUS_OFFLINE == adev->card_status) {
2466 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302467 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302468 goto error_config;
2469 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302470
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302471 if (audio_is_bluetooth_sco_device(in->device)) {
2472 if (!adev->bt_sco_on) {
2473 ALOGE("%s: SCO profile is not ready, return error", __func__);
2474 ret = -EIO;
2475 goto error_config;
2476 }
2477 }
2478
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002479 /* Check if source matches incall recording usecase criteria */
2480 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2481 if (ret)
2482 goto error_config;
2483 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002484 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2485
2486 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2487 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2488 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002489 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002490 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002491
Eric Laurentb23d5282013-05-14 15:27:20 -07002492 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493 if (in->pcm_device_id < 0) {
2494 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2495 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002496 ret = -EINVAL;
2497 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002499
2500 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002502
2503 if (!uc_info) {
2504 ret = -ENOMEM;
2505 goto error_config;
2506 }
2507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508 uc_info->id = in->usecase;
2509 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002510 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002511 uc_info->devices = in->device;
2512 uc_info->in_snd_device = SND_DEVICE_NONE;
2513 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002515 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302516 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2517 adev->perf_lock_opts,
2518 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002519 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520
Derek Chend2530072014-11-24 12:39:14 -08002521 if (uc_info->in_snd_device != SND_DEVICE_NONE) {
2522 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2523 ALOGE("%s: failed to start ext hw plugin", __func__);
2524 }
2525
Haynes Mathew George16081042017-05-31 17:16:49 -07002526 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302527 ret = audio_extn_cin_start_input_stream(in);
2528 if (ret)
2529 goto error_open;
2530 else
2531 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002532 }
2533
Haynes Mathew George16081042017-05-31 17:16:49 -07002534 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002535 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002536 ALOGE("%s: pcm stream not ready", __func__);
2537 goto error_open;
2538 }
2539 ret = pcm_start(in->pcm);
2540 if (ret < 0) {
2541 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2542 goto error_open;
2543 }
2544 } else {
2545 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2546 unsigned int pcm_open_retry_count = 0;
2547
2548 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2549 flags |= PCM_MMAP | PCM_NOIRQ;
2550 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2551 } else if (in->realtime) {
2552 flags |= PCM_MMAP | PCM_NOIRQ;
2553 }
2554
Garmond Leunge2433c32017-09-28 21:51:22 -07002555 if (audio_extn_ffv_get_stream() == in) {
2556 ALOGD("%s: ffv stream, update pcm config", __func__);
2557 audio_extn_ffv_update_pcm_config(&config);
2558 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002559 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2560 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2561
2562 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002563 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002564 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002565 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002566 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302567 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302568 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2569 adev->card_status = CARD_STATUS_OFFLINE;
2570 in->card_status = CARD_STATUS_OFFLINE;
2571 ret = -EIO;
2572 goto error_open;
2573 }
2574
Haynes Mathew George16081042017-05-31 17:16:49 -07002575 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2576 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2577 if (in->pcm != NULL) {
2578 pcm_close(in->pcm);
2579 in->pcm = NULL;
2580 }
2581 if (pcm_open_retry_count-- == 0) {
2582 ret = -EIO;
2583 goto error_open;
2584 }
2585 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2586 continue;
2587 }
2588 break;
2589 }
2590
2591 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002592 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002593 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002594 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002595 if (ret < 0) {
2596 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2597 pcm_close(in->pcm);
2598 in->pcm = NULL;
2599 goto error_open;
2600 }
2601 register_in_stream(in);
2602 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002603 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002604 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002605 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002606 if (ret < 0) {
2607 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002608 pcm_close(in->pcm);
2609 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002610 goto error_open;
2611 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002612 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002613 }
2614
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002615 check_and_enable_effect(adev);
2616
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302617done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302618 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002619 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302620 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002621 return ret;
2622
2623error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302624 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002625 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002626error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302627 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302628 /*
2629 * sleep 50ms to allow sufficient time for kernel
2630 * drivers to recover incases like SSR.
2631 */
2632 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002633 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302634 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002635 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636}
2637
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002638void lock_input_stream(struct stream_in *in)
2639{
2640 pthread_mutex_lock(&in->pre_lock);
2641 pthread_mutex_lock(&in->lock);
2642 pthread_mutex_unlock(&in->pre_lock);
2643}
2644
2645void lock_output_stream(struct stream_out *out)
2646{
2647 pthread_mutex_lock(&out->pre_lock);
2648 pthread_mutex_lock(&out->lock);
2649 pthread_mutex_unlock(&out->pre_lock);
2650}
2651
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002652/* must be called with out->lock locked */
2653static int send_offload_cmd_l(struct stream_out* out, int command)
2654{
2655 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2656
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002657 if (!cmd) {
2658 ALOGE("failed to allocate mem for command 0x%x", command);
2659 return -ENOMEM;
2660 }
2661
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002662 ALOGVV("%s %d", __func__, command);
2663
2664 cmd->cmd = command;
2665 list_add_tail(&out->offload_cmd_list, &cmd->node);
2666 pthread_cond_signal(&out->offload_cond);
2667 return 0;
2668}
2669
2670/* must be called iwth out->lock locked */
2671static void stop_compressed_output_l(struct stream_out *out)
2672{
2673 out->offload_state = OFFLOAD_STATE_IDLE;
2674 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002675 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002676 if (out->compr != NULL) {
2677 compress_stop(out->compr);
2678 while (out->offload_thread_blocked) {
2679 pthread_cond_wait(&out->cond, &out->lock);
2680 }
2681 }
2682}
2683
Varun Balaraje49253e2017-07-06 19:48:56 +05302684bool is_interactive_usecase(audio_usecase_t uc_id)
2685{
2686 unsigned int i;
2687 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2688 if (uc_id == interactive_usecases[i])
2689 return true;
2690 }
2691 return false;
2692}
2693
2694static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2695{
2696 audio_usecase_t ret_uc = USECASE_INVALID;
2697 unsigned int intract_uc_index;
2698 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2699
2700 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2701 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2702 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2703 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2704 ret_uc = interactive_usecases[intract_uc_index];
2705 break;
2706 }
2707 }
2708
2709 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2710 return ret_uc;
2711}
2712
2713static void free_interactive_usecase(struct audio_device *adev,
2714 audio_usecase_t uc_id)
2715{
2716 unsigned int interact_uc_index;
2717 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2718
2719 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2720 if (interactive_usecases[interact_uc_index] == uc_id) {
2721 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2722 break;
2723 }
2724 }
2725 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2726}
2727
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002728bool is_offload_usecase(audio_usecase_t uc_id)
2729{
2730 unsigned int i;
2731 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2732 if (uc_id == offload_usecases[i])
2733 return true;
2734 }
2735 return false;
2736}
2737
Dhananjay Kumarac341582017-02-23 23:42:25 +05302738static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002739{
vivek mehta446c3962015-09-14 10:57:35 -07002740 audio_usecase_t ret_uc = USECASE_INVALID;
2741 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002742 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002743 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302744 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002745 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2746 else
2747 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002748
vivek mehta446c3962015-09-14 10:57:35 -07002749 pthread_mutex_lock(&adev->lock);
2750 if (get_usecase_from_list(adev, ret_uc) != NULL)
2751 ret_uc = USECASE_INVALID;
2752 pthread_mutex_unlock(&adev->lock);
2753
2754 return ret_uc;
2755 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002756
2757 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002758 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2759 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2760 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2761 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002762 break;
2763 }
2764 }
vivek mehta446c3962015-09-14 10:57:35 -07002765
2766 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2767 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002768}
2769
2770static void free_offload_usecase(struct audio_device *adev,
2771 audio_usecase_t uc_id)
2772{
vivek mehta446c3962015-09-14 10:57:35 -07002773 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002774 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002775
2776 if (!adev->multi_offload_enable)
2777 return;
2778
2779 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2780 if (offload_usecases[offload_uc_index] == uc_id) {
2781 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002782 break;
2783 }
2784 }
2785 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2786}
2787
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002788static void *offload_thread_loop(void *context)
2789{
2790 struct stream_out *out = (struct stream_out *) context;
2791 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002792 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002793
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002794 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2795 set_sched_policy(0, SP_FOREGROUND);
2796 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2797
2798 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002799 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002800 for (;;) {
2801 struct offload_cmd *cmd = NULL;
2802 stream_callback_event_t event;
2803 bool send_callback = false;
2804
2805 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2806 __func__, list_empty(&out->offload_cmd_list),
2807 out->offload_state);
2808 if (list_empty(&out->offload_cmd_list)) {
2809 ALOGV("%s SLEEPING", __func__);
2810 pthread_cond_wait(&out->offload_cond, &out->lock);
2811 ALOGV("%s RUNNING", __func__);
2812 continue;
2813 }
2814
2815 item = list_head(&out->offload_cmd_list);
2816 cmd = node_to_item(item, struct offload_cmd, node);
2817 list_remove(item);
2818
2819 ALOGVV("%s STATE %d CMD %d out->compr %p",
2820 __func__, out->offload_state, cmd->cmd, out->compr);
2821
2822 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2823 free(cmd);
2824 break;
2825 }
2826
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002827 // allow OFFLOAD_CMD_ERROR reporting during standby
2828 // this is needed to handle failures during compress_open
2829 // Note however that on a pause timeout, the stream is closed
2830 // and no offload usecase will be active. Therefore this
2831 // special case is needed for compress_open failures alone
2832 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2833 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002834 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002835 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002836 pthread_cond_signal(&out->cond);
2837 continue;
2838 }
2839 out->offload_thread_blocked = true;
2840 pthread_mutex_unlock(&out->lock);
2841 send_callback = false;
2842 switch(cmd->cmd) {
2843 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002844 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002845 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002846 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002847 send_callback = true;
2848 event = STREAM_CBK_EVENT_WRITE_READY;
2849 break;
2850 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002851 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302852 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002853 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302854 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002855 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302856 if (ret < 0)
2857 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302858 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302859 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002860 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002861 else
2862 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002863 if (-ENETRESET != ret && !(-EINTR == ret &&
2864 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302865 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302866 pthread_mutex_lock(&out->lock);
2867 out->send_new_metadata = 1;
2868 out->send_next_track_params = true;
2869 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302870 event = STREAM_CBK_EVENT_DRAIN_READY;
2871 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2872 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302873 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002874 break;
2875 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002876 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002877 ret = compress_drain(out->compr);
2878 ALOGD("copl(%p):out of compress_drain", out);
2879 // EINTR check avoids drain interruption due to SSR
2880 if (-ENETRESET != ret && !(-EINTR == ret &&
2881 CARD_STATUS_OFFLINE == out->card_status)) {
2882 send_callback = true;
2883 event = STREAM_CBK_EVENT_DRAIN_READY;
2884 } else
2885 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002886 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302887 case OFFLOAD_CMD_ERROR:
2888 ALOGD("copl(%p): sending error callback to AF", out);
2889 send_callback = true;
2890 event = STREAM_CBK_EVENT_ERROR;
2891 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892 default:
2893 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2894 break;
2895 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002896 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002897 out->offload_thread_blocked = false;
2898 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002899 if (send_callback && out->client_callback) {
2900 ALOGVV("%s: sending client_callback event %d", __func__, event);
2901 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002902 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002903 free(cmd);
2904 }
2905
2906 pthread_cond_signal(&out->cond);
2907 while (!list_empty(&out->offload_cmd_list)) {
2908 item = list_head(&out->offload_cmd_list);
2909 list_remove(item);
2910 free(node_to_item(item, struct offload_cmd, node));
2911 }
2912 pthread_mutex_unlock(&out->lock);
2913
2914 return NULL;
2915}
2916
2917static int create_offload_callback_thread(struct stream_out *out)
2918{
2919 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2920 list_init(&out->offload_cmd_list);
2921 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2922 offload_thread_loop, out);
2923 return 0;
2924}
2925
2926static int destroy_offload_callback_thread(struct stream_out *out)
2927{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002928 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002929 stop_compressed_output_l(out);
2930 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2931
2932 pthread_mutex_unlock(&out->lock);
2933 pthread_join(out->offload_thread, (void **) NULL);
2934 pthread_cond_destroy(&out->offload_cond);
2935
2936 return 0;
2937}
2938
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002939static int stop_output_stream(struct stream_out *out)
2940{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302941 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942 struct audio_usecase *uc_info;
2943 struct audio_device *adev = out->dev;
2944
Eric Laurent994a6932013-07-17 11:51:42 -07002945 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002946 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002947 uc_info = get_usecase_from_list(adev, out->usecase);
2948 if (uc_info == NULL) {
2949 ALOGE("%s: Could not find the usecase (%d) in the list",
2950 __func__, out->usecase);
2951 return -EINVAL;
2952 }
2953
Derek Chend2530072014-11-24 12:39:14 -08002954 if (uc_info->out_snd_device != SND_DEVICE_NONE) {
2955 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2956 ALOGE("%s: failed to stop ext hw plugin", __func__);
2957 }
2958
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002959 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302960 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002961 if (adev->visualizer_stop_output != NULL)
2962 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002963
2964 audio_extn_dts_remove_state_notifier_node(out->usecase);
2965
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002966 if (adev->offload_effects_stop_output != NULL)
2967 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2968 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002969
Arun Mirpurief53ce52018-09-11 18:00:09 -07002970 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2971 voice_set_device_mute_flag(adev, false);
2972
Eric Laurent150dbfe2013-02-27 14:31:02 -08002973 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002974 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002975
2976 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002977 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002978
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002979 if (is_offload_usecase(out->usecase)) {
2980 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2981 adev->dsp_bit_width_enforce_mode,
2982 false);
2983 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07002984 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2985 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
2986 false);
2987
2988 if (ret != 0)
2989 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
2990 /* default service interval was successfully updated,
2991 reopen USB backend with new service interval */
2992 ret = 0;
2993 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002994
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002995 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302996 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002997 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302998 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002999 ALOGV("Disable passthrough , reset mixer to pcm");
3000 /* NO_PASSTHROUGH */
3001 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003002 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003003 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3004 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003005
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303006 /* Must be called after removing the usecase from list */
3007 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303008 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303009
Manish Dewangan21a850a2017-08-14 12:03:55 +05303010 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003011 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3012 if (ret < 0)
3013 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3014 }
3015
Garmond Leung5fd0b552018-04-17 11:56:12 -07003016 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003017 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018 return ret;
3019}
3020
3021int start_output_stream(struct stream_out *out)
3022{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024 struct audio_usecase *uc_info;
3025 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003026 char mixer_ctl_name[128];
3027 struct mixer_ctl *ctl = NULL;
3028 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303029 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030
Haynes Mathew George380745d2017-10-04 15:27:45 -07003031 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003032 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3033 ret = -EINVAL;
3034 goto error_config;
3035 }
3036
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303037 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
3038 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
3039 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303040
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303041 if (CARD_STATUS_OFFLINE == out->card_status ||
3042 CARD_STATUS_OFFLINE == adev->card_status) {
3043 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303044 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303045 goto error_config;
3046 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303047
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303048 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003049 if (!audio_extn_a2dp_source_is_ready()) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303050 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303051 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303052 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303053 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3054 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3055 ret = -EAGAIN;
3056 goto error_config;
3057 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303058 }
3059 }
3060 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303061 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3062 if (!adev->bt_sco_on) {
3063 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3064 //combo usecase just by pass a2dp
3065 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3066 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3067 } else {
3068 ALOGE("%s: SCO profile is not ready, return error", __func__);
3069 ret = -EAGAIN;
3070 goto error_config;
3071 }
3072 }
3073 }
3074
Eric Laurentb23d5282013-05-14 15:27:20 -07003075 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076 if (out->pcm_device_id < 0) {
3077 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3078 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003079 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003080 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081 }
3082
3083 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003084
3085 if (!uc_info) {
3086 ret = -ENOMEM;
3087 goto error_config;
3088 }
3089
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090 uc_info->id = out->usecase;
3091 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003092 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003093 uc_info->devices = out->devices;
3094 uc_info->in_snd_device = SND_DEVICE_NONE;
3095 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003096
3097 /* This must be called before adding this usecase to the list */
3098 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3099 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3100 /* USB backend is not reopened immediately.
3101 This is eventually done as part of select_devices */
3102 }
3103
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003104 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303106 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3107 adev->perf_lock_opts,
3108 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303109
3110 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303111 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303112 if (audio_extn_passthru_is_enabled() &&
3113 audio_extn_passthru_is_passthrough_stream(out)) {
3114 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303115 }
3116 }
3117
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303118 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003119 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303120 if (!a2dp_combo) {
3121 check_a2dp_restore_l(adev, out, false);
3122 } else {
3123 audio_devices_t dev = out->devices;
3124 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3125 select_devices(adev, out->usecase);
3126 out->devices = dev;
3127 }
3128 } else {
3129 select_devices(adev, out->usecase);
3130 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003131
Arun Mirpurief53ce52018-09-11 18:00:09 -07003132 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3133 voice_set_device_mute_flag(adev, true);
3134
Derek Chend2530072014-11-24 12:39:14 -08003135 if (uc_info->out_snd_device != SND_DEVICE_NONE) {
3136 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3137 ALOGE("%s: failed to start ext hw plugin", __func__);
3138 }
3139
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003140 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3141 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003142
3143 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3144 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3145 ALOGE("%s: pcm stream not ready", __func__);
3146 goto error_open;
3147 }
3148 ret = pcm_start(out->pcm);
3149 if (ret < 0) {
3150 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3151 goto error_open;
3152 }
3153 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003154 unsigned int flags = PCM_OUT;
3155 unsigned int pcm_open_retry_count = 0;
3156 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3157 flags |= PCM_MMAP | PCM_NOIRQ;
3158 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003159 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003160 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003161 } else
3162 flags |= PCM_MONOTONIC;
3163
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003164 if ((adev->vr_audio_mode_enabled) &&
3165 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3166 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3167 "PCM_Dev %d Topology", out->pcm_device_id);
3168 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3169 if (!ctl) {
3170 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3171 __func__, mixer_ctl_name);
3172 } else {
3173 //if success use ULLPP
3174 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3175 __func__, mixer_ctl_name, out->pcm_device_id);
3176 //There is a still a possibility that some sessions
3177 // that request for FAST|RAW when 3D audio is active
3178 //can go through ULLPP. Ideally we expects apps to
3179 //listen to audio focus and stop concurrent playback
3180 //Also, we will look for mode flag (voice_in_communication)
3181 //before enabling the realtime flag.
3182 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3183 }
3184 }
3185
Surendar Karka91fa3682018-07-02 18:12:12 +05303186 if (out->realtime)
3187 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3188 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3189
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003190 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003191 ATRACE_BEGIN("pcm_open");
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003192 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3193 flags, &out->config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003194 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303195 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303196 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3197 out->card_status = CARD_STATUS_OFFLINE;
3198 adev->card_status = CARD_STATUS_OFFLINE;
3199 ret = -EIO;
3200 goto error_open;
3201 }
3202
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003203 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3204 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3205 if (out->pcm != NULL) {
3206 pcm_close(out->pcm);
3207 out->pcm = NULL;
3208 }
3209 if (pcm_open_retry_count-- == 0) {
3210 ret = -EIO;
3211 goto error_open;
3212 }
3213 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3214 continue;
3215 }
3216 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003217 }
Surendar Karka91fa3682018-07-02 18:12:12 +05303218 if (!out->realtime)
3219 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303220 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003221
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003222 ALOGV("%s: pcm_prepare", __func__);
3223 if (pcm_is_ready(out->pcm)) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003224 ATRACE_BEGIN("pcm_prepare");
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003225 ret = pcm_prepare(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003226 ATRACE_END();
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003227 if (ret < 0) {
3228 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3229 pcm_close(out->pcm);
3230 out->pcm = NULL;
3231 goto error_open;
3232 }
3233 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08003234 // apply volume for voip playback after path is set up
3235 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3236 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303237 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) &&
3238 (out->apply_volume)) {
3239 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3240 out->apply_volume = false;
3241 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003242 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003243 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303244 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003245 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3246 adev->dsp_bit_width_enforce_mode,
3247 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003248 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003249 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003250 out->compr = compress_open(adev->snd_card,
3251 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003252 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003253 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303254 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303255 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3256 adev->card_status = CARD_STATUS_OFFLINE;
3257 out->card_status = CARD_STATUS_OFFLINE;
3258 ret = -EIO;
3259 goto error_open;
3260 }
3261
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003262 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003263 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003264 compress_close(out->compr);
3265 out->compr = NULL;
3266 ret = -EIO;
3267 goto error_open;
3268 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303269 /* compress_open sends params of the track, so reset the flag here */
3270 out->is_compr_metadata_avail = false;
3271
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003272 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003273 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003274
Fred Oh3f43e742015-03-04 18:42:34 -08003275 /* Since small bufs uses blocking writes, a write will be blocked
3276 for the default max poll time (20s) in the event of an SSR.
3277 Reduce the poll time to observe and deal with SSR faster.
3278 */
Ashish Jain5106d362016-05-11 19:23:33 +05303279 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003280 compress_set_max_poll_wait(out->compr, 1000);
3281 }
3282
Manish Dewangan69426c82017-01-30 17:35:36 +05303283 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303284 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303285
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003286 audio_extn_dts_create_state_notifier_node(out->usecase);
3287 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3288 popcount(out->channel_mask),
3289 out->playback_started);
3290
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003291#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303292 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003293 audio_extn_dolby_send_ddp_endp_params(adev);
3294#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303295 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3296 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003297 if (adev->visualizer_start_output != NULL)
3298 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3299 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303300 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003301 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003302 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003303 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003304
3305 if (ret == 0) {
3306 register_out_stream(out);
3307 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003308 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3309 ALOGE("%s: pcm stream not ready", __func__);
3310 goto error_open;
3311 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003312 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003313 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003314 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003315 if (ret < 0)
3316 goto error_open;
3317 }
3318 }
3319
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303320 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003321 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003322
Manish Dewangan21a850a2017-08-14 12:03:55 +05303323 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003324 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003325 if (ret < 0)
3326 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3327 }
3328
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003329 // consider a scenario where on pause lower layers are tear down.
3330 // so on resume, swap mixer control need to be sent only when
3331 // backend is active, hence rather than sending from enable device
3332 // sending it from start of streamtream
3333
3334 platform_set_swap_channels(adev, true);
3335
Haynes Mathew George380745d2017-10-04 15:27:45 -07003336 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303337 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003338 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003339error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303340 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003342error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303343 /*
3344 * sleep 50ms to allow sufficient time for kernel
3345 * drivers to recover incases like SSR.
3346 */
3347 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003348 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303349 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003350 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351}
3352
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353static int check_input_parameters(uint32_t sample_rate,
3354 audio_format_t format,
3355 int channel_count)
3356{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003357 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003358
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303359 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3360 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3361 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003362 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003363 !audio_extn_compr_cap_format_supported(format) &&
3364 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003365 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003366
3367 switch (channel_count) {
3368 case 1:
3369 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303370 case 3:
3371 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003372 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003373 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003374 break;
3375 default:
3376 ret = -EINVAL;
3377 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003378
3379 switch (sample_rate) {
3380 case 8000:
3381 case 11025:
3382 case 12000:
3383 case 16000:
3384 case 22050:
3385 case 24000:
3386 case 32000:
3387 case 44100:
3388 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003389 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303390 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003391 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303392 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393 break;
3394 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003395 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396 }
3397
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003398 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399}
3400
Naresh Tanniru04f71882018-06-26 17:46:22 +05303401
3402/** Add a value in a list if not already present.
3403 * @return true if value was successfully inserted or already present,
3404 * false if the list is full and does not contain the value.
3405 */
3406static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3407 for (size_t i = 0; i < list_length; i++) {
3408 if (list[i] == value) return true; // value is already present
3409 if (list[i] == 0) { // no values in this slot
3410 list[i] = value;
3411 return true; // value inserted
3412 }
3413 }
3414 return false; // could not insert value
3415}
3416
3417/** Add channel_mask in supported_channel_masks if not already present.
3418 * @return true if channel_mask was successfully inserted or already present,
3419 * false if supported_channel_masks is full and does not contain channel_mask.
3420 */
3421static void register_channel_mask(audio_channel_mask_t channel_mask,
3422 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3423 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3424 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3425}
3426
3427/** Add format in supported_formats if not already present.
3428 * @return true if format was successfully inserted or already present,
3429 * false if supported_formats is full and does not contain format.
3430 */
3431static void register_format(audio_format_t format,
3432 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3433 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3434 "%s: stream can not declare supporting its format %x", __func__, format);
3435}
3436/** Add sample_rate in supported_sample_rates if not already present.
3437 * @return true if sample_rate was successfully inserted or already present,
3438 * false if supported_sample_rates is full and does not contain sample_rate.
3439 */
3440static void register_sample_rate(uint32_t sample_rate,
3441 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3442 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3443 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3444}
3445
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003446static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3447{
3448 uint32_t high = num1, low = num2, temp = 0;
3449
3450 if (!num1 || !num2)
3451 return 0;
3452
3453 if (num1 < num2) {
3454 high = num2;
3455 low = num1;
3456 }
3457
3458 while (low != 0) {
3459 temp = low;
3460 low = high % low;
3461 high = temp;
3462 }
3463 return (num1 * num2)/high;
3464}
3465
3466static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3467{
3468 uint32_t remainder = 0;
3469
3470 if (!multiplier)
3471 return num;
3472
3473 remainder = num % multiplier;
3474 if (remainder)
3475 num += (multiplier - remainder);
3476
3477 return num;
3478}
3479
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003480static size_t get_input_buffer_size(uint32_t sample_rate,
3481 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003482 int channel_count,
3483 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484{
3485 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003486 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003487
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003488 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3489 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003491 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003492 if (is_low_latency)
3493 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303494
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003495 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
3496 size *= bytes_per_period_sample;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497
Ralf Herzbd08d632018-09-28 15:50:49 +02003498 /* make sure the size is multiple of 32 bytes and additionally multiple of
3499 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003500 * At 48 kHz mono 16-bit PCM:
3501 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3502 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003503 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003504 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003505 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003506
3507 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508}
3509
Ashish Jain058165c2016-09-28 23:18:48 +05303510static size_t get_output_period_size(uint32_t sample_rate,
3511 audio_format_t format,
3512 int channel_count,
3513 int duration /*in millisecs*/)
3514{
3515 size_t size = 0;
3516 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3517
3518 if ((duration == 0) || (sample_rate == 0) ||
3519 (bytes_per_sample == 0) || (channel_count == 0)) {
3520 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3521 bytes_per_sample, channel_count);
3522 return -EINVAL;
3523 }
3524
3525 size = (sample_rate *
3526 duration *
3527 bytes_per_sample *
3528 channel_count) / 1000;
3529 /*
3530 * To have same PCM samples for all channels, the buffer size requires to
3531 * be multiple of (number of channels * bytes per sample)
3532 * For writes to succeed, the buffer must be written at address which is multiple of 32
3533 */
3534 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3535
3536 return (size/(channel_count * bytes_per_sample));
3537}
3538
Zhou Song48453a02018-01-10 17:50:59 +08003539static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303540{
3541 uint64_t actual_frames_rendered = 0;
3542 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3543
3544 /* This adjustment accounts for buffering after app processor.
3545 * It is based on estimated DSP latency per use case, rather than exact.
3546 */
3547 int64_t platform_latency = platform_render_latency(out->usecase) *
3548 out->sample_rate / 1000000LL;
3549
Zhou Song48453a02018-01-10 17:50:59 +08003550 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303551 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3552 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3553 * hence only estimate.
3554 */
3555 int64_t signed_frames = out->written - kernel_buffer_size;
3556
3557 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3558
Zhou Song48453a02018-01-10 17:50:59 +08003559 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303560 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003561 if (timestamp != NULL )
3562 *timestamp = out->writeAt;
3563 } else if (timestamp != NULL) {
3564 clock_gettime(CLOCK_MONOTONIC, timestamp);
3565 }
3566 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303567
3568 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3569 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3570 (long long int)out->written, (int)kernel_buffer_size,
3571 audio_bytes_per_sample(out->compr_config.codec->format),
3572 popcount(out->channel_mask));
3573
3574 return actual_frames_rendered;
3575}
3576
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3578{
3579 struct stream_out *out = (struct stream_out *)stream;
3580
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003581 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582}
3583
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003584static int out_set_sample_rate(struct audio_stream *stream __unused,
3585 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586{
3587 return -ENOSYS;
3588}
3589
3590static size_t out_get_buffer_size(const struct audio_stream *stream)
3591{
3592 struct stream_out *out = (struct stream_out *)stream;
3593
Varun Balaraje49253e2017-07-06 19:48:56 +05303594 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303595 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303596 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303597 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3598 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3599 else
3600 return out->compr_config.fragment_size;
3601 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003602 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003603 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3604 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 +05303605 else if (is_offload_usecase(out->usecase) &&
3606 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303607 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003608
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003609 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003610 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611}
3612
3613static uint32_t out_get_channels(const struct audio_stream *stream)
3614{
3615 struct stream_out *out = (struct stream_out *)stream;
3616
3617 return out->channel_mask;
3618}
3619
3620static audio_format_t out_get_format(const struct audio_stream *stream)
3621{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003622 struct stream_out *out = (struct stream_out *)stream;
3623
3624 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625}
3626
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003627static int out_set_format(struct audio_stream *stream __unused,
3628 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629{
3630 return -ENOSYS;
3631}
3632
3633static int out_standby(struct audio_stream *stream)
3634{
3635 struct stream_out *out = (struct stream_out *)stream;
3636 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003637 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003638
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303639 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3640 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003642 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003643 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003644 if (adev->adm_deregister_stream)
3645 adev->adm_deregister_stream(adev->adm_data, out->handle);
3646
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003647 if (is_offload_usecase(out->usecase))
3648 stop_compressed_output_l(out);
3649
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003650 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003652 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3653 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303654 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003655 pthread_mutex_unlock(&adev->lock);
3656 pthread_mutex_unlock(&out->lock);
3657 ALOGD("VOIP output entered standby");
3658 return 0;
3659 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003660 if (out->pcm) {
3661 pcm_close(out->pcm);
3662 out->pcm = NULL;
3663 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003664 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3665 do_stop = out->playback_started;
3666 out->playback_started = false;
3667 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003668 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003669 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303670 out->send_next_track_params = false;
3671 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003672 out->gapless_mdata.encoder_delay = 0;
3673 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003674 if (out->compr != NULL) {
3675 compress_close(out->compr);
3676 out->compr = NULL;
3677 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003678 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003679 if (do_stop) {
3680 stop_output_stream(out);
3681 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003682 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003683 }
3684 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303685 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686 return 0;
3687}
3688
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303689static int out_on_error(struct audio_stream *stream)
3690{
3691 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003692 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303693
3694 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003695 // always send CMD_ERROR for offload streams, this
3696 // is needed e.g. when SSR happens within compress_open
3697 // since the stream is active, offload_callback_thread is also active.
3698 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3699 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003700 }
3701 pthread_mutex_unlock(&out->lock);
3702
3703 status = out_standby(&out->stream.common);
3704
3705 lock_output_stream(out);
3706 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003707 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303708 }
3709 pthread_mutex_unlock(&out->lock);
3710
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003711 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303712}
3713
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303714/*
3715 *standby implementation without locks, assumes that the callee already
3716 *has taken adev and out lock.
3717 */
3718int out_standby_l(struct audio_stream *stream)
3719{
3720 struct stream_out *out = (struct stream_out *)stream;
3721 struct audio_device *adev = out->dev;
3722
3723 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3724 stream, out->usecase, use_case_table[out->usecase]);
3725
3726 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003727 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303728 if (adev->adm_deregister_stream)
3729 adev->adm_deregister_stream(adev->adm_data, out->handle);
3730
3731 if (is_offload_usecase(out->usecase))
3732 stop_compressed_output_l(out);
3733
3734 out->standby = true;
3735 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3736 voice_extn_compress_voip_close_output_stream(stream);
3737 out->started = 0;
3738 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003739 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303740 return 0;
3741 } else if (!is_offload_usecase(out->usecase)) {
3742 if (out->pcm) {
3743 pcm_close(out->pcm);
3744 out->pcm = NULL;
3745 }
3746 } else {
3747 ALOGD("copl(%p):standby", out);
3748 out->send_next_track_params = false;
3749 out->is_compr_metadata_avail = false;
3750 out->gapless_mdata.encoder_delay = 0;
3751 out->gapless_mdata.encoder_padding = 0;
3752 if (out->compr != NULL) {
3753 compress_close(out->compr);
3754 out->compr = NULL;
3755 }
3756 }
3757 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003758 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303759 }
3760 ALOGD("%s: exit", __func__);
3761 return 0;
3762}
3763
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003764static int out_dump(const struct audio_stream *stream __unused,
3765 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766{
3767 return 0;
3768}
3769
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003770static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3771{
3772 int ret = 0;
3773 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003774
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003775 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003776 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003777 return -EINVAL;
3778 }
3779
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303780 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003781
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003782 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3783 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303784 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003785 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003786 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3787 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303788 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003789 }
3790
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003791 ALOGV("%s new encoder delay %u and padding %u", __func__,
3792 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3793
3794 return 0;
3795}
3796
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003797static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3798{
3799 return out == adev->primary_output || out == adev->voice_tx_output;
3800}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003801
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303802// note: this call is safe only if the stream_cb is
3803// removed first in close_output_stream (as is done now).
3804static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3805{
3806 if (!stream || !parms)
3807 return;
3808
3809 struct stream_out *out = (struct stream_out *)stream;
3810 struct audio_device *adev = out->dev;
3811
3812 card_status_t status;
3813 int card;
3814 if (parse_snd_card_status(parms, &card, &status) < 0)
3815 return;
3816
3817 pthread_mutex_lock(&adev->lock);
3818 bool valid_cb = (card == adev->snd_card);
3819 pthread_mutex_unlock(&adev->lock);
3820
3821 if (!valid_cb)
3822 return;
3823
3824 lock_output_stream(out);
3825 if (out->card_status != status)
3826 out->card_status = status;
3827 pthread_mutex_unlock(&out->lock);
3828
3829 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3830 use_case_table[out->usecase],
3831 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3832
3833 if (status == CARD_STATUS_OFFLINE)
3834 out_on_error(stream);
3835
3836 return;
3837}
3838
Kevin Rocardfce19002017-08-07 19:21:36 -07003839static int get_alive_usb_card(struct str_parms* parms) {
3840 int card;
3841 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
3842 !audio_extn_usb_alive(card)) {
3843 return card;
3844 }
3845 return -ENODEV;
3846}
3847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3849{
3850 struct stream_out *out = (struct stream_out *)stream;
3851 struct audio_device *adev = out->dev;
3852 struct str_parms *parms;
3853 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003854 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303855 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003856 bool reconfig = false;
3857 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003858
sangwoobc677242013-08-08 16:53:43 +09003859 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003860 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303862 if (!parms)
3863 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003864 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3865 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003867 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003868 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003869
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003870 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003871 * When HDMI cable is unplugged the music playback is paused and
3872 * the policy manager sends routing=0. But the audioflinger continues
3873 * to write data until standby time (3sec). As the HDMI core is
3874 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003875 * Avoid this by routing audio to speaker until standby.
3876 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003877 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3878 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303879 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003880 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3881 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003882 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303883 /*
3884 * When A2DP is disconnected the
3885 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02003886 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303887 * (3sec). As BT is turned off, the write gets blocked.
3888 * Avoid this by routing audio to speaker until standby.
3889 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003890 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07003891 (val == AUDIO_DEVICE_NONE) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003892 !audio_extn_a2dp_source_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303893 val = AUDIO_DEVICE_OUT_SPEAKER;
3894 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05303895 /*
3896 * When USB headset is disconnected the music platback paused
3897 * and the policy manager send routing=0. But if the USB is connected
3898 * back before the standby time, AFE is not closed and opened
3899 * when USB is connected back. So routing to speker will guarantee
3900 * AFE reconfiguration and AFE will be opend once USB is connected again
3901 */
3902 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
3903 (val == AUDIO_DEVICE_NONE) &&
3904 !audio_extn_usb_connected(parms)) {
3905 val = AUDIO_DEVICE_OUT_SPEAKER;
3906 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303907 /* To avoid a2dp to sco overlapping / BT device improper state
3908 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303909 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303910 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003911 if (!audio_extn_a2dp_source_is_ready()) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303912 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3913 //combo usecase just by pass a2dp
3914 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303915 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303916 } else {
3917 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3918 /* update device to a2dp and don't route as BT returned error
3919 * However it is still possible a2dp routing called because
3920 * of current active device disconnection (like wired headset)
3921 */
3922 out->devices = val;
3923 pthread_mutex_unlock(&out->lock);
3924 pthread_mutex_unlock(&adev->lock);
3925 goto error;
3926 }
3927 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303928 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003929
3930 audio_devices_t new_dev = val;
3931
3932 // Workaround: If routing to an non existing usb device, fail gracefully
3933 // The routing request will otherwise block during 10 second
3934 int card;
3935 if (audio_is_usb_out_device(new_dev) &&
3936 (card = get_alive_usb_card(parms)) >= 0) {
3937
3938 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
3939 pthread_mutex_unlock(&adev->lock);
3940 pthread_mutex_unlock(&out->lock);
3941 ret = -ENOSYS;
3942 goto routing_fail;
3943 }
3944
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003945 /*
3946 * select_devices() call below switches all the usecases on the same
3947 * backend to the new device. Refer to check_usecases_codec_backend() in
3948 * the select_devices(). But how do we undo this?
3949 *
3950 * For example, music playback is active on headset (deep-buffer usecase)
3951 * and if we go to ringtones and select a ringtone, low-latency usecase
3952 * will be started on headset+speaker. As we can't enable headset+speaker
3953 * and headset devices at the same time, select_devices() switches the music
3954 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3955 * So when the ringtone playback is completed, how do we undo the same?
3956 *
3957 * We are relying on the out_set_parameters() call on deep-buffer output,
3958 * once the ringtone playback is ended.
3959 * NOTE: We should not check if the current devices are same as new devices.
3960 * Because select_devices() must be called to switch back the music
3961 * playback to headset.
3962 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003963 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003964 audio_devices_t new_dev = val;
3965 bool same_dev = out->devices == new_dev;
3966 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003967
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003968 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08003969 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003970 if (adev->mode == AUDIO_MODE_IN_CALL) {
3971 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003972 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3973 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
3974 audio_extn_usb_set_service_interval(true /*playback*/,
3975 service_interval,
3976 &reconfig);
3977 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
3978 }
3979 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003980 }
3981 } else {
3982 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003983 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003984 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003985 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003986
3987 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003988 if (!same_dev) {
3989 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303990 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3991 adev->perf_lock_opts,
3992 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003993 if (adev->adm_on_routing_change)
3994 adev->adm_on_routing_change(adev->adm_data,
3995 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003996 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303997 if (!bypass_a2dp) {
3998 select_devices(adev, out->usecase);
3999 } else {
4000 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
4001 select_devices(adev, out->usecase);
4002 out->devices = new_dev;
4003 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004004
4005 if (!same_dev) {
4006 // on device switch force swap, lower functions will make sure
4007 // to check if swap is allowed or not.
4008 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304009 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004010 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304011 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4012 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004013 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304014 pthread_mutex_lock(&out->compr_mute_lock);
4015 out->a2dp_compress_mute = false;
4016 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4017 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004018 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4019 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304020 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004021 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004022 }
4023
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004025 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004026 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004027 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004028
4029 if (out == adev->primary_output) {
4030 pthread_mutex_lock(&adev->lock);
4031 audio_extn_set_parameters(adev, parms);
4032 pthread_mutex_unlock(&adev->lock);
4033 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004034 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004035 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004036 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004037
4038 audio_extn_dts_create_state_notifier_node(out->usecase);
4039 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4040 popcount(out->channel_mask),
4041 out->playback_started);
4042
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004043 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004044 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004045
Surendar Karkaf51b5842018-04-26 11:28:38 +05304046 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4047 sizeof(value));
4048 if (err >= 0) {
4049 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4050 audio_extn_send_dual_mono_mixing_coefficients(out);
4051 }
4052
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304053 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4054 if (err >= 0) {
4055 strlcpy(out->profile, value, sizeof(out->profile));
4056 ALOGV("updating stream profile with value '%s'", out->profile);
4057 lock_output_stream(out);
4058 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4059 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004060 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304061 out->sample_rate, out->bit_width,
4062 out->channel_mask, out->profile,
4063 &out->app_type_cfg);
4064 pthread_mutex_unlock(&out->lock);
4065 }
4066
Alexy Joseph98988832017-01-13 14:56:59 -08004067 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004068 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4069 // and vendor.audio.hal.output.suspend.supported is set to true
4070 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004071 //check suspend parameter only for low latency and if the property
4072 //is enabled
4073 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4074 ALOGI("%s: got suspend_playback %s", __func__, value);
4075 lock_output_stream(out);
4076 if (!strncmp(value, "false", 5)) {
4077 //suspend_playback=false is supposed to set QOS value back to 75%
4078 //the mixer control sent with value Enable will achieve that
4079 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4080 } else if (!strncmp (value, "true", 4)) {
4081 //suspend_playback=true is supposed to remove QOS value
4082 //resetting the mixer control will set the default value
4083 //for the mixer control which is Disable and this removes the QOS vote
4084 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4085 } else {
4086 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4087 " got %s", __func__, value);
4088 ret = -1;
4089 }
4090
4091 if (ret != 0) {
4092 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4093 __func__, out->pm_qos_mixer_path, ret);
4094 }
4095
4096 pthread_mutex_unlock(&out->lock);
4097 }
4098 }
4099 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004100 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304101error:
Eric Laurent994a6932013-07-17 11:51:42 -07004102 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004103 return ret;
4104}
4105
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004106static bool stream_get_parameter_channels(struct str_parms *query,
4107 struct str_parms *reply,
4108 audio_channel_mask_t *supported_channel_masks) {
4109 int ret = -1;
4110 char value[512];
4111 bool first = true;
4112 size_t i, j;
4113
4114 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4115 ret = 0;
4116 value[0] = '\0';
4117 i = 0;
4118 while (supported_channel_masks[i] != 0) {
4119 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4120 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4121 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304122 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004123
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304124 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004125 first = false;
4126 break;
4127 }
4128 }
4129 i++;
4130 }
4131 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4132 }
4133 return ret == 0;
4134}
4135
4136static bool stream_get_parameter_formats(struct str_parms *query,
4137 struct str_parms *reply,
4138 audio_format_t *supported_formats) {
4139 int ret = -1;
4140 char value[256];
4141 size_t i, j;
4142 bool first = true;
4143
4144 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4145 ret = 0;
4146 value[0] = '\0';
4147 i = 0;
4148 while (supported_formats[i] != 0) {
4149 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4150 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4151 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304152 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004153 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304154 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004155 first = false;
4156 break;
4157 }
4158 }
4159 i++;
4160 }
4161 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4162 }
4163 return ret == 0;
4164}
4165
4166static bool stream_get_parameter_rates(struct str_parms *query,
4167 struct str_parms *reply,
4168 uint32_t *supported_sample_rates) {
4169
4170 int i;
4171 char value[256];
4172 int ret = -1;
4173 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4174 ret = 0;
4175 value[0] = '\0';
4176 i=0;
4177 int cursor = 0;
4178 while (supported_sample_rates[i]) {
4179 int avail = sizeof(value) - cursor;
4180 ret = snprintf(value + cursor, avail, "%s%d",
4181 cursor > 0 ? "|" : "",
4182 supported_sample_rates[i]);
4183 if (ret < 0 || ret >= avail) {
4184 // if cursor is at the last element of the array
4185 // overwrite with \0 is duplicate work as
4186 // snprintf already put a \0 in place.
4187 // else
4188 // we had space to write the '|' at value[cursor]
4189 // (which will be overwritten) or no space to fill
4190 // the first element (=> cursor == 0)
4191 value[cursor] = '\0';
4192 break;
4193 }
4194 cursor += ret;
4195 ++i;
4196 }
4197 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4198 value);
4199 }
4200 return ret >= 0;
4201}
4202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004203static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4204{
4205 struct stream_out *out = (struct stream_out *)stream;
4206 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004207 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004208 char value[256];
4209 struct str_parms *reply = str_parms_create();
4210 size_t i, j;
4211 int ret;
4212 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004213
4214 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004215 if (reply) {
4216 str_parms_destroy(reply);
4217 }
4218 if (query) {
4219 str_parms_destroy(query);
4220 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004221 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4222 return NULL;
4223 }
4224
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004225 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004226 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4227 if (ret >= 0) {
4228 value[0] = '\0';
4229 i = 0;
4230 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004231 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4232 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004233 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004234 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004235 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004236 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004237 first = false;
4238 break;
4239 }
4240 }
4241 i++;
4242 }
4243 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4244 str = str_parms_to_str(reply);
4245 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004246 voice_extn_out_get_parameters(out, query, reply);
4247 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004248 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004249
Alexy Joseph62142aa2015-11-16 15:10:34 -08004250
4251 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4252 if (ret >= 0) {
4253 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304254 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4255 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004256 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304257 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004258 } else {
4259 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304260 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004261 }
4262 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004263 if (str)
4264 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004265 str = str_parms_to_str(reply);
4266 }
4267
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004268 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4269 if (ret >= 0) {
4270 value[0] = '\0';
4271 i = 0;
4272 first = true;
4273 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004274 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4275 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004276 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004277 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004278 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004279 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004280 first = false;
4281 break;
4282 }
4283 }
4284 i++;
4285 }
4286 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004287 if (str)
4288 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004289 str = str_parms_to_str(reply);
4290 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004291
4292 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4293 if (ret >= 0) {
4294 value[0] = '\0';
4295 i = 0;
4296 first = true;
4297 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004298 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4299 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004300 if (!first) {
4301 strlcat(value, "|", sizeof(value));
4302 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004303 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004304 first = false;
4305 break;
4306 }
4307 }
4308 i++;
4309 }
4310 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4311 if (str)
4312 free(str);
4313 str = str_parms_to_str(reply);
4314 }
4315
Alexy Joseph98988832017-01-13 14:56:59 -08004316 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4317 //only low latency track supports suspend_resume
4318 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004319 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004320 if (str)
4321 free(str);
4322 str = str_parms_to_str(reply);
4323 }
4324
4325
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004326 str_parms_destroy(query);
4327 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004328 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004329 return str;
4330}
4331
4332static uint32_t out_get_latency(const struct audio_stream_out *stream)
4333{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004334 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004335 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004336 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004337
Alexy Josephaa54c872014-12-03 02:46:47 -08004338 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304339 lock_output_stream(out);
4340 latency = audio_extn_utils_compress_get_dsp_latency(out);
4341 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004342 } else if ((out->realtime) ||
4343 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004344 // since the buffer won't be filled up faster than realtime,
4345 // return a smaller number
4346 if (out->config.rate)
4347 period_ms = (out->af_period_multiplier * out->config.period_size *
4348 1000) / (out->config.rate);
4349 else
4350 period_ms = 0;
4351 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004352 } else {
4353 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004354 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004355 }
4356
yidongh0515e042017-07-06 15:00:34 +08004357 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004358 latency += audio_extn_a2dp_get_encoder_latency();
4359
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304360 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004361 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004362}
4363
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304364static float AmpToDb(float amplification)
4365{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304366 float db = DSD_VOLUME_MIN_DB;
4367 if (amplification > 0) {
4368 db = 20 * log10(amplification);
4369 if(db < DSD_VOLUME_MIN_DB)
4370 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304371 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304372 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304373}
4374
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304375static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4376 float right)
4377{
4378 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304379 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304380 char mixer_ctl_name[128];
4381 struct audio_device *adev = out->dev;
4382 struct mixer_ctl *ctl;
4383 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4384 PCM_PLAYBACK);
4385
4386 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4387 "Compress Playback %d Volume", pcm_device_id);
4388 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4389 if (!ctl) {
4390 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4391 __func__, mixer_ctl_name);
4392 return -EINVAL;
4393 }
4394 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4395 __func__, mixer_ctl_name, left, right);
4396 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4397 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4398 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4399
4400 return 0;
4401}
4402
Zhou Song2b8f28f2017-09-11 10:51:38 +08004403static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4404 float right)
4405{
4406 struct stream_out *out = (struct stream_out *)stream;
4407 char mixer_ctl_name[] = "App Type Gain";
4408 struct audio_device *adev = out->dev;
4409 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304410 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004411
4412 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4413 if (!ctl) {
4414 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4415 __func__, mixer_ctl_name);
4416 return -EINVAL;
4417 }
4418
4419 set_values[0] = 0; //0: Rx Session 1:Tx Session
4420 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304421 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4422 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004423
4424 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4425 return 0;
4426}
4427
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304428static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
4429 float right)
4430{
4431 struct stream_out *out = (struct stream_out *)stream;
4432 /* Volume control for pcm playback */
4433 if (left != right) {
4434 return -EINVAL;
4435 } else {
4436 char mixer_ctl_name[128];
4437 struct audio_device *adev = out->dev;
4438 struct mixer_ctl *ctl;
4439 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4440 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
4441 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4442 if (!ctl) {
4443 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
4444 return -EINVAL;
4445 }
4446
4447 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
4448 int ret = mixer_ctl_set_value(ctl, 0, volume);
4449 if (ret < 0) {
4450 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
4451 return -EINVAL;
4452 }
4453
4454 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
4455
4456 return 0;
4457 }
4458}
4459
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004460static int out_set_volume(struct audio_stream_out *stream, float left,
4461 float right)
4462{
Eric Laurenta9024de2013-04-04 09:19:12 -07004463 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004464 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304465 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004466
Eric Laurenta9024de2013-04-04 09:19:12 -07004467 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4468 /* only take left channel into account: the API is for stereo anyway */
4469 out->muted = (left == 0.0f);
4470 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004471 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304472 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004473 /*
4474 * Set mute or umute on HDMI passthrough stream.
4475 * Only take left channel into account.
4476 * Mute is 0 and unmute 1
4477 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304478 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304479 } else if (out->format == AUDIO_FORMAT_DSD){
4480 char mixer_ctl_name[128] = "DSD Volume";
4481 struct audio_device *adev = out->dev;
4482 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4483
4484 if (!ctl) {
4485 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4486 __func__, mixer_ctl_name);
4487 return -EINVAL;
4488 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304489 volume[0] = (long)(AmpToDb(left));
4490 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304491 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4492 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004493 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304494 pthread_mutex_lock(&out->compr_mute_lock);
4495 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
4496 if (!out->a2dp_compress_mute)
4497 ret = out_set_compr_volume(stream, left, right);
4498 out->volume_l = left;
4499 out->volume_r = right;
4500 pthread_mutex_unlock(&out->compr_mute_lock);
4501 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004502 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004503 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004504 if (!out->standby)
4505 ret = out_set_voip_volume(stream, left, right);
4506 out->volume_l = left;
4507 out->volume_r = right;
4508 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304509 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
4510 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) {
4511 /* Volume control for pcm playback */
4512 if (!out->standby)
4513 ret = out_set_pcm_volume(stream, left, right);
4514 else
4515 out->apply_volume = true;
4516
4517 out->volume_l = left;
4518 out->volume_r = right;
4519 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004520 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004521
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004522 return -ENOSYS;
4523}
4524
Zhou Songc9672822017-08-16 16:01:39 +08004525static void update_frames_written(struct stream_out *out, size_t bytes)
4526{
4527 size_t bpf = 0;
4528
4529 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4530 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4531 bpf = 1;
4532 else if (!is_offload_usecase(out->usecase))
4533 bpf = audio_bytes_per_sample(out->format) *
4534 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004535
4536 pthread_mutex_lock(&out->position_query_lock);
4537 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004538 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004539 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4540 }
4541 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004542}
4543
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004544static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4545 size_t bytes)
4546{
4547 struct stream_out *out = (struct stream_out *)stream;
4548 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004549 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304550 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004551 const size_t frame_size = audio_stream_out_frame_size(stream);
4552 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004553
Haynes Mathew George380745d2017-10-04 15:27:45 -07004554 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004555 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304556
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304557 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004558
Dhananjay Kumarac341582017-02-23 23:42:25 +05304559 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304560 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304561 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4562 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004563 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304564 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304565 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304566 ALOGD(" %s: sound card is not active/SSR state", __func__);
4567 ret= -EIO;
4568 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304569 }
4570 }
4571
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304572 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304573 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304574 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304575 goto exit;
4576 }
4577
Haynes Mathew George16081042017-05-31 17:16:49 -07004578 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4579 ret = -EINVAL;
4580 goto exit;
4581 }
4582
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304583 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4584 !out->is_iec61937_info_available) {
4585
4586 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4587 out->is_iec61937_info_available = true;
4588 } else if (audio_extn_passthru_is_enabled()) {
4589 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304590 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304591
4592 if((out->format == AUDIO_FORMAT_DTS) ||
4593 (out->format == AUDIO_FORMAT_DTS_HD)) {
4594 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4595 buffer, bytes);
4596 if (ret) {
4597 if (ret != -ENOSYS) {
4598 out->is_iec61937_info_available = false;
4599 ALOGD("iec61937 transmission info not yet updated retry");
4600 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304601 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304602 /* if stream has started and after that there is
4603 * stream config change (iec transmission config)
4604 * then trigger select_device to update backend configuration.
4605 */
4606 out->stream_config_changed = true;
4607 pthread_mutex_lock(&adev->lock);
4608 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304609 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4610 ret = -EINVAL;
4611 goto exit;
4612 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304613 pthread_mutex_unlock(&adev->lock);
4614 out->stream_config_changed = false;
4615 out->is_iec61937_info_available = true;
4616 }
4617 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304618
Garmond Leung317cbf12017-09-13 16:20:50 -07004619 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304620 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4621 (out->is_iec61937_info_available == true)) {
4622 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4623 ret = -EINVAL;
4624 goto exit;
4625 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304626 }
4627 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304628
4629 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004630 (audio_extn_a2dp_source_is_suspended())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304631 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4632 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304633 ret = -EIO;
4634 goto exit;
4635 }
4636 }
4637 }
4638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004639 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004640 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004641 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004642 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4643 ret = voice_extn_compress_voip_start_output_stream(out);
4644 else
4645 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004646 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004647 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004648 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004649 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650 goto exit;
4651 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304652 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004653 if (last_known_cal_step != -1) {
4654 ALOGD("%s: retry previous failed cal level set", __func__);
4655 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304656 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004657 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304658
4659 if ((out->is_iec61937_info_available == true) &&
4660 (audio_extn_passthru_is_passthrough_stream(out))&&
4661 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4662 ret = -EINVAL;
4663 goto exit;
4664 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05304665 if (out->set_dual_mono)
4666 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004667 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004668
Ashish Jain81eb2a82015-05-13 10:52:34 +05304669 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004670 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304671 adev->is_channel_status_set = true;
4672 }
4673
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004674 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004675 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004676 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004677 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004678 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4679 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304680 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4681 ALOGD("copl(%p):send next track params in gapless", out);
4682 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4683 out->send_next_track_params = false;
4684 out->is_compr_metadata_avail = false;
4685 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004686 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304687 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304688 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004689
Ashish Jain83a6cc22016-06-28 14:34:17 +05304690 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304691 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304692 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304693 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004694 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304695 return -EINVAL;
4696 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304697 audio_format_t dst_format = out->hal_op_format;
4698 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304699
Dieter Luecking5d57def2018-09-07 14:23:37 +02004700 /* prevent division-by-zero */
4701 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
4702 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
4703 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
4704 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05304705 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02004706 ATRACE_END();
4707 return -EINVAL;
4708 }
4709
Ashish Jainf1eaa582016-05-23 20:54:24 +05304710 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4711 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4712
Ashish Jain83a6cc22016-06-28 14:34:17 +05304713 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304714 dst_format,
4715 buffer,
4716 src_format,
4717 frames);
4718
Ashish Jain83a6cc22016-06-28 14:34:17 +05304719 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304720 bytes_to_write);
4721
4722 /*Convert written bytes in audio flinger format*/
4723 if (ret > 0)
4724 ret = ((ret * format_to_bitwidth_table[out->format]) /
4725 format_to_bitwidth_table[dst_format]);
4726 }
4727 } else
4728 ret = compress_write(out->compr, buffer, bytes);
4729
Zhou Songc9672822017-08-16 16:01:39 +08004730 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4731 update_frames_written(out, bytes);
4732
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304733 if (ret < 0)
4734 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08004735 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304736 /*msg to cb thread only if non blocking write is enabled*/
4737 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304738 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004739 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304740 } else if (-ENETRESET == ret) {
4741 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304742 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304743 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304744 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004745 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304746 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004747 }
Ashish Jain5106d362016-05-11 19:23:33 +05304748
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304749 /* Call compr start only when non-zero bytes of data is there to be rendered */
4750 if (!out->playback_started && ret > 0) {
4751 int status = compress_start(out->compr);
4752 if (status < 0) {
4753 ret = status;
4754 ALOGE("%s: compr start failed with err %d", __func__, errno);
4755 goto exit;
4756 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004757 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004758 out->playback_started = 1;
4759 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004760
4761 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4762 popcount(out->channel_mask),
4763 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004764 }
4765 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004766 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004767 return ret;
4768 } else {
4769 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004770 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004771 if (out->muted)
4772 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004773 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
4774 __func__, frames, frame_size, bytes_to_write);
4775
4776 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
4777 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4778 int16_t *src = (int16_t *)buffer;
4779 int16_t *dst = (int16_t *)buffer;
4780
4781 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
4782 out->format != AUDIO_FORMAT_PCM_16_BIT,
4783 "out_write called for incall music use case with wrong properties");
4784
4785 /*
4786 * FIXME: this can be removed once audio flinger mixer supports
4787 * mono output
4788 */
4789
4790 /*
4791 * Code below goes over each frame in the buffer and adds both
4792 * L and R samples and then divides by 2 to convert to mono
4793 */
4794 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
4795 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
4796 }
4797 bytes_to_write /= 2;
4798 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004799
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304800 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004801
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004802 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004803
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004804 if (out->config.rate)
4805 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4806 out->config.rate;
4807
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004808 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004809 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4810
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004811 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004812 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004813 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304814 out->convert_buffer != NULL) {
4815
4816 memcpy_by_audio_format(out->convert_buffer,
4817 out->hal_op_format,
4818 buffer,
4819 out->hal_ip_format,
4820 out->config.period_size * out->config.channels);
4821
4822 ret = pcm_write(out->pcm, out->convert_buffer,
4823 (out->config.period_size *
4824 out->config.channels *
4825 format_to_bitwidth_table[out->hal_op_format]));
4826 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304827 /*
4828 * To avoid underrun in DSP when the application is not pumping
4829 * data at required rate, check for the no. of bytes and ignore
4830 * pcm_write if it is less than actual buffer size.
4831 * It is a work around to a change in compress VOIP driver.
4832 */
4833 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4834 bytes < (out->config.period_size * out->config.channels *
4835 audio_bytes_per_sample(out->format))) {
4836 size_t voip_buf_size =
4837 out->config.period_size * out->config.channels *
4838 audio_bytes_per_sample(out->format);
4839 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4840 __func__, bytes, voip_buf_size);
4841 usleep(((uint64_t)voip_buf_size - bytes) *
4842 1000000 / audio_stream_out_frame_size(stream) /
4843 out_get_sample_rate(&out->stream.common));
4844 ret = 0;
4845 } else
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004846 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304847 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004848
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004849 release_out_focus(out);
4850
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304851 if (ret < 0)
4852 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004853 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304854 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004855 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004856 }
4857
4858exit:
Zhou Songc9672822017-08-16 16:01:39 +08004859 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304860 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304861 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304862 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004863 pthread_mutex_unlock(&out->lock);
4864
4865 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004866 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004867 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304868 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304869 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304870 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304871 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304872 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304873 out->standby = true;
4874 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304875 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02004876 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
4877 /* prevent division-by-zero */
4878 uint32_t stream_size = audio_stream_out_frame_size(stream);
4879 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004880
Dieter Luecking5d57def2018-09-07 14:23:37 +02004881 if ((stream_size == 0) || (srate == 0)) {
4882 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
4883 ATRACE_END();
4884 return -EINVAL;
4885 }
4886 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
4887 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004888 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05304889 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004890 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004891 return ret;
4892 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004893 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004894 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004895 return bytes;
4896}
4897
4898static int out_get_render_position(const struct audio_stream_out *stream,
4899 uint32_t *dsp_frames)
4900{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004901 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004902
4903 if (dsp_frames == NULL)
4904 return -EINVAL;
4905
4906 *dsp_frames = 0;
4907 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004908 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304909
4910 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4911 * this operation and adev_close_output_stream(where out gets reset).
4912 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304913 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004914 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05304915 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004916 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304917 return 0;
4918 }
4919
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004920 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304921 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304922 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004923 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304924 if (ret < 0)
4925 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004926 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304927 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004928 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304929 if (-ENETRESET == ret) {
4930 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304931 out->card_status = CARD_STATUS_OFFLINE;
4932 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304933 } else if(ret < 0) {
4934 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304935 ret = -EINVAL;
4936 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304937 /*
4938 * Handle corner case where compress session is closed during SSR
4939 * and timestamp is queried
4940 */
4941 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304942 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304943 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304944 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004945 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05304946 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304947 pthread_mutex_unlock(&out->lock);
4948 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004949 } else if (audio_is_linear_pcm(out->format)) {
4950 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004951 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08004952 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004953 } else
4954 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004955}
4956
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004957static int out_add_audio_effect(const struct audio_stream *stream __unused,
4958 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004959{
4960 return 0;
4961}
4962
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004963static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4964 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004965{
4966 return 0;
4967}
4968
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004969static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4970 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004971{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304972 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004973}
4974
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004975static int out_get_presentation_position(const struct audio_stream_out *stream,
4976 uint64_t *frames, struct timespec *timestamp)
4977{
4978 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05304979 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07004980 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004981
Ashish Jain5106d362016-05-11 19:23:33 +05304982 /* below piece of code is not guarded against any lock because audioFliner serializes
4983 * this operation and adev_close_output_stream( where out gets reset).
4984 */
4985 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304986 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004987 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05304988 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4989 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4990 return 0;
4991 }
4992
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004993 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004994
Ashish Jain5106d362016-05-11 19:23:33 +05304995 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4996 ret = compress_get_tstamp(out->compr, &dsp_frames,
4997 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004998 // Adjustment accounts for A2dp encoder latency with offload usecases
4999 // Note: Encoder latency is returned in ms.
5000 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5001 unsigned long offset =
5002 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5003 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5004 }
Ashish Jain5106d362016-05-11 19:23:33 +05305005 ALOGVV("%s rendered frames %ld sample_rate %d",
5006 __func__, dsp_frames, out->sample_rate);
5007 *frames = dsp_frames;
5008 if (ret < 0)
5009 ret = -errno;
5010 if (-ENETRESET == ret) {
5011 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305012 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305013 ret = -EINVAL;
5014 } else
5015 ret = 0;
5016 /* this is the best we can do */
5017 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005018 } else {
5019 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005020 unsigned int avail;
5021 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5022 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5023 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5024 // This adjustment accounts for buffering after app processor.
5025 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005026 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005027 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005028
Weiyin Jiangd4633762018-03-16 12:05:03 +08005029 // Adjustment accounts for A2dp encoder latency with non offload usecases
5030 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5031 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5032 signed_frames -=
5033 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5034 }
5035
5036 // It would be unusual for this value to be negative, but check just in case ...
5037 if (signed_frames >= 0) {
5038 *frames = signed_frames;
5039 ret = 0;
5040 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005041 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305042 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305043 *frames = out->written;
5044 clock_gettime(CLOCK_MONOTONIC, timestamp);
5045 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005046 }
5047 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005048 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005049 return ret;
5050}
5051
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005052static int out_set_callback(struct audio_stream_out *stream,
5053 stream_callback_t callback, void *cookie)
5054{
5055 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005056 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005057
5058 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005059 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005060 out->client_callback = callback;
5061 out->client_cookie = cookie;
5062 if (out->adsp_hdlr_stream_handle) {
5063 ret = audio_extn_adsp_hdlr_stream_set_callback(
5064 out->adsp_hdlr_stream_handle,
5065 callback,
5066 cookie);
5067 if (ret)
5068 ALOGW("%s:adsp hdlr callback registration failed %d",
5069 __func__, ret);
5070 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005071 pthread_mutex_unlock(&out->lock);
5072 return 0;
5073}
5074
5075static int out_pause(struct audio_stream_out* stream)
5076{
5077 struct stream_out *out = (struct stream_out *)stream;
5078 int status = -ENOSYS;
5079 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005080 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005081 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005082 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005083 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305084 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305085 status = compress_pause(out->compr);
5086
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005087 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005088
Mingming Yin21854652016-04-13 11:54:02 -07005089 if (audio_extn_passthru_is_active()) {
5090 ALOGV("offload use case, pause passthru");
5091 audio_extn_passthru_on_pause(out);
5092 }
5093
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305094 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005095 audio_extn_dts_notify_playback_state(out->usecase, 0,
5096 out->sample_rate, popcount(out->channel_mask),
5097 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005098 }
5099 pthread_mutex_unlock(&out->lock);
5100 }
5101 return status;
5102}
5103
5104static int out_resume(struct audio_stream_out* stream)
5105{
5106 struct stream_out *out = (struct stream_out *)stream;
5107 int status = -ENOSYS;
5108 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005109 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005110 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005111 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005112 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005113 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305114 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305115 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005116 }
5117 if (!status) {
5118 out->offload_state = OFFLOAD_STATE_PLAYING;
5119 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305120 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005121 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5122 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005123 }
5124 pthread_mutex_unlock(&out->lock);
5125 }
5126 return status;
5127}
5128
5129static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5130{
5131 struct stream_out *out = (struct stream_out *)stream;
5132 int status = -ENOSYS;
5133 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005134 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005135 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005136 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5137 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5138 else
5139 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5140 pthread_mutex_unlock(&out->lock);
5141 }
5142 return status;
5143}
5144
5145static int out_flush(struct audio_stream_out* stream)
5146{
5147 struct stream_out *out = (struct stream_out *)stream;
5148 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005149 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005150 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005151 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005152 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5153 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005154 } else {
5155 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5156 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005157 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005158 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005159 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005160 return 0;
5161 }
5162 return -ENOSYS;
5163}
5164
Haynes Mathew George16081042017-05-31 17:16:49 -07005165static int out_stop(const struct audio_stream_out* stream)
5166{
5167 struct stream_out *out = (struct stream_out *)stream;
5168 struct audio_device *adev = out->dev;
5169 int ret = -ENOSYS;
5170
5171 ALOGV("%s", __func__);
5172 pthread_mutex_lock(&adev->lock);
5173 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5174 out->playback_started && out->pcm != NULL) {
5175 pcm_stop(out->pcm);
5176 ret = stop_output_stream(out);
5177 out->playback_started = false;
5178 }
5179 pthread_mutex_unlock(&adev->lock);
5180 return ret;
5181}
5182
5183static int out_start(const struct audio_stream_out* stream)
5184{
5185 struct stream_out *out = (struct stream_out *)stream;
5186 struct audio_device *adev = out->dev;
5187 int ret = -ENOSYS;
5188
5189 ALOGV("%s", __func__);
5190 pthread_mutex_lock(&adev->lock);
5191 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5192 !out->playback_started && out->pcm != NULL) {
5193 ret = start_output_stream(out);
5194 if (ret == 0) {
5195 out->playback_started = true;
5196 }
5197 }
5198 pthread_mutex_unlock(&adev->lock);
5199 return ret;
5200}
5201
5202/*
5203 * Modify config->period_count based on min_size_frames
5204 */
5205static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5206{
5207 int periodCountRequested = (min_size_frames + config->period_size - 1)
5208 / config->period_size;
5209 int periodCount = MMAP_PERIOD_COUNT_MIN;
5210
5211 ALOGV("%s original config.period_size = %d config.period_count = %d",
5212 __func__, config->period_size, config->period_count);
5213
5214 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5215 periodCount *= 2;
5216 }
5217 config->period_count = periodCount;
5218
5219 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5220}
5221
5222static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5223 int32_t min_size_frames,
5224 struct audio_mmap_buffer_info *info)
5225{
5226 struct stream_out *out = (struct stream_out *)stream;
5227 struct audio_device *adev = out->dev;
5228 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005229 unsigned int offset1 = 0;
5230 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005231 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005232 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005233
5234 ALOGV("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305235 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005236 pthread_mutex_lock(&adev->lock);
5237
Sharad Sanglec6f32552018-05-04 16:15:38 +05305238 if (CARD_STATUS_OFFLINE == out->card_status ||
5239 CARD_STATUS_OFFLINE == adev->card_status) {
5240 ALOGW("out->card_status or adev->card_status offline, try again");
5241 ret = -EIO;
5242 goto exit;
5243 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005244 if (info == NULL || min_size_frames == 0) {
5245 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5246 ret = -EINVAL;
5247 goto exit;
5248 }
5249 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5250 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5251 ret = -ENOSYS;
5252 goto exit;
5253 }
5254 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5255 if (out->pcm_device_id < 0) {
5256 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5257 __func__, out->pcm_device_id, out->usecase);
5258 ret = -EINVAL;
5259 goto exit;
5260 }
5261
5262 adjust_mmap_period_count(&out->config, min_size_frames);
5263
5264 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5265 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5266 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5267 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305268 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305269 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5270 out->card_status = CARD_STATUS_OFFLINE;
5271 adev->card_status = CARD_STATUS_OFFLINE;
5272 ret = -EIO;
5273 goto exit;
5274 }
5275
Haynes Mathew George16081042017-05-31 17:16:49 -07005276 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5277 step = "open";
5278 ret = -ENODEV;
5279 goto exit;
5280 }
5281 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5282 if (ret < 0) {
5283 step = "begin";
5284 goto exit;
5285 }
5286 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
5287 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005288 ret = platform_get_mmap_data_fd(adev->platform,
5289 out->pcm_device_id, 0 /*playback*/,
5290 &info->shared_memory_fd,
5291 &mmap_size);
5292 if (ret < 0) {
5293 step = "get_mmap_fd";
5294 goto exit;
5295 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005296 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005297 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005298
5299 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5300 if (ret < 0) {
5301 step = "commit";
5302 goto exit;
5303 }
5304
5305 out->standby = false;
5306 ret = 0;
5307
5308 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5309 __func__, info->shared_memory_address, info->buffer_size_frames);
5310
5311exit:
5312 if (ret != 0) {
5313 if (out->pcm == NULL) {
5314 ALOGE("%s: %s - %d", __func__, step, ret);
5315 } else {
5316 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5317 pcm_close(out->pcm);
5318 out->pcm = NULL;
5319 }
5320 }
5321 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305322 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005323 return ret;
5324}
5325
5326static int out_get_mmap_position(const struct audio_stream_out *stream,
5327 struct audio_mmap_position *position)
5328{
5329 struct stream_out *out = (struct stream_out *)stream;
5330 ALOGVV("%s", __func__);
5331 if (position == NULL) {
5332 return -EINVAL;
5333 }
5334 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005335 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005336 return -ENOSYS;
5337 }
5338 if (out->pcm == NULL) {
5339 return -ENOSYS;
5340 }
5341
5342 struct timespec ts = { 0, 0 };
5343 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5344 if (ret < 0) {
5345 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5346 return ret;
5347 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005348 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005349 return 0;
5350}
5351
5352
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005353/** audio_stream_in implementation **/
5354static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5355{
5356 struct stream_in *in = (struct stream_in *)stream;
5357
5358 return in->config.rate;
5359}
5360
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005361static int in_set_sample_rate(struct audio_stream *stream __unused,
5362 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005363{
5364 return -ENOSYS;
5365}
5366
5367static size_t in_get_buffer_size(const struct audio_stream *stream)
5368{
5369 struct stream_in *in = (struct stream_in *)stream;
5370
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005371 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5372 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005373 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5374 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 -07005375 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5376 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305377 else if(audio_extn_cin_attached_usecase(in->usecase))
5378 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005379
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005380 return in->config.period_size * in->af_period_multiplier *
5381 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005382}
5383
5384static uint32_t in_get_channels(const struct audio_stream *stream)
5385{
5386 struct stream_in *in = (struct stream_in *)stream;
5387
5388 return in->channel_mask;
5389}
5390
5391static audio_format_t in_get_format(const struct audio_stream *stream)
5392{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005393 struct stream_in *in = (struct stream_in *)stream;
5394
5395 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005396}
5397
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005398static int in_set_format(struct audio_stream *stream __unused,
5399 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005400{
5401 return -ENOSYS;
5402}
5403
5404static int in_standby(struct audio_stream *stream)
5405{
5406 struct stream_in *in = (struct stream_in *)stream;
5407 struct audio_device *adev = in->dev;
5408 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305409 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5410 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005411 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305412
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005413 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005414 if (!in->standby && in->is_st_session) {
5415 ALOGD("%s: sound trigger pcm stop lab", __func__);
5416 audio_extn_sound_trigger_stop_lab(in);
5417 in->standby = 1;
5418 }
5419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005420 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005421 if (adev->adm_deregister_stream)
5422 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5423
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005424 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005425 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005426 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005427 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005428 voice_extn_compress_voip_close_input_stream(stream);
5429 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005430 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5431 do_stop = in->capture_started;
5432 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005433 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305434 if (audio_extn_cin_attached_usecase(in->usecase))
5435 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005436 }
5437
5438 if (do_stop) {
Zhou Songa8895042016-07-05 17:54:22 +08005439 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005440 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005441 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005442 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005443 in->pcm = NULL;
5444 }
5445 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005446 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08005447 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005448 }
5449 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005450 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005451 return status;
5452}
5453
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005454static int in_dump(const struct audio_stream *stream __unused,
5455 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005456{
5457 return 0;
5458}
5459
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305460static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5461{
5462 if (!stream || !parms)
5463 return;
5464
5465 struct stream_in *in = (struct stream_in *)stream;
5466 struct audio_device *adev = in->dev;
5467
5468 card_status_t status;
5469 int card;
5470 if (parse_snd_card_status(parms, &card, &status) < 0)
5471 return;
5472
5473 pthread_mutex_lock(&adev->lock);
5474 bool valid_cb = (card == adev->snd_card);
5475 pthread_mutex_unlock(&adev->lock);
5476
5477 if (!valid_cb)
5478 return;
5479
5480 lock_input_stream(in);
5481 if (in->card_status != status)
5482 in->card_status = status;
5483 pthread_mutex_unlock(&in->lock);
5484
5485 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5486 use_case_table[in->usecase],
5487 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5488
5489 // a better solution would be to report error back to AF and let
5490 // it put the stream to standby
5491 if (status == CARD_STATUS_OFFLINE)
5492 in_standby(&in->stream.common);
5493
5494 return;
5495}
5496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005497static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5498{
5499 struct stream_in *in = (struct stream_in *)stream;
5500 struct audio_device *adev = in->dev;
5501 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005502 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005503 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005504
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305505 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005506 parms = str_parms_create_str(kvpairs);
5507
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305508 if (!parms)
5509 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005510 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005511 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005512
5513 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5514 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005515 val = atoi(value);
5516 /* no audio source uses val == 0 */
5517 if ((in->source != val) && (val != 0)) {
5518 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005519 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5520 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5521 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005522 (in->config.rate == 8000 || in->config.rate == 16000 ||
5523 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005524 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005525 err = voice_extn_compress_voip_open_input_stream(in);
5526 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005527 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005528 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005529 }
5530 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005531 }
5532 }
5533
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005534 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5535 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005536 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005537 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5538
5539 // Workaround: If routing to an non existing usb device, fail gracefully
5540 // The routing request will otherwise block during 10 second
5541 int card;
5542 if (audio_is_usb_in_device(val) &&
5543 (card = get_alive_usb_card(parms)) >= 0) {
5544
5545 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5546 ret = -ENOSYS;
5547 } else {
5548
5549 in->device = val;
5550 /* If recording is in progress, change the tx device to new device */
5551 if (!in->standby && !in->is_st_session) {
5552 ALOGV("update input routing change");
5553 // inform adm before actual routing to prevent glitches.
5554 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005555 adev->adm_on_routing_change(adev->adm_data,
5556 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005557 ret = select_devices(adev, in->usecase);
5558 }
5559 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005560 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005561 }
5562 }
5563
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305564 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5565 if (err >= 0) {
5566 strlcpy(in->profile, value, sizeof(in->profile));
5567 ALOGV("updating stream profile with value '%s'", in->profile);
5568 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5569 &adev->streams_input_cfg_list,
5570 in->device, in->flags, in->format,
5571 in->sample_rate, in->bit_width,
5572 in->profile, &in->app_type_cfg);
5573 }
5574
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005575 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005576 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005577
5578 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305579error:
Eric Laurent994a6932013-07-17 11:51:42 -07005580 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005581 return ret;
5582}
5583
5584static char* in_get_parameters(const struct audio_stream *stream,
5585 const char *keys)
5586{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005587 struct stream_in *in = (struct stream_in *)stream;
5588 struct str_parms *query = str_parms_create_str(keys);
5589 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005590 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005591
5592 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005593 if (reply) {
5594 str_parms_destroy(reply);
5595 }
5596 if (query) {
5597 str_parms_destroy(query);
5598 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005599 ALOGE("in_get_parameters: failed to create query or reply");
5600 return NULL;
5601 }
5602
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005603 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005604
5605 voice_extn_in_get_parameters(in, query, reply);
5606
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005607 stream_get_parameter_channels(query, reply,
5608 &in->supported_channel_masks[0]);
5609 stream_get_parameter_formats(query, reply,
5610 &in->supported_formats[0]);
5611 stream_get_parameter_rates(query, reply,
5612 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005613 str = str_parms_to_str(reply);
5614 str_parms_destroy(query);
5615 str_parms_destroy(reply);
5616
5617 ALOGV("%s: exit: returns - %s", __func__, str);
5618 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005619}
5620
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005621static int in_set_gain(struct audio_stream_in *stream __unused,
5622 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005623{
5624 return 0;
5625}
5626
5627static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5628 size_t bytes)
5629{
5630 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305631
5632 if (in == NULL) {
5633 ALOGE("%s: stream_in ptr is NULL", __func__);
5634 return -EINVAL;
5635 }
5636
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005637 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305638 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305639 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005640
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005641 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305642
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005643 if (in->is_st_session) {
5644 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5645 /* Read from sound trigger HAL */
5646 audio_extn_sound_trigger_read(in, buffer, bytes);
5647 pthread_mutex_unlock(&in->lock);
5648 return bytes;
5649 }
5650
Haynes Mathew George16081042017-05-31 17:16:49 -07005651 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5652 ret = -ENOSYS;
5653 goto exit;
5654 }
5655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005656 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005657 pthread_mutex_lock(&adev->lock);
5658 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5659 ret = voice_extn_compress_voip_start_input_stream(in);
5660 else
5661 ret = start_input_stream(in);
5662 pthread_mutex_unlock(&adev->lock);
5663 if (ret != 0) {
5664 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005665 }
5666 in->standby = 0;
5667 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005668
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005669 // what's the duration requested by the client?
5670 long ns = 0;
5671
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305672 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005673 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5674 in->config.rate;
5675
5676 request_in_focus(in, ns);
5677 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005678
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305679 if (audio_extn_cin_attached_usecase(in->usecase)) {
5680 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5681 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305682 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005683 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305684 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005685 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005686 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005687 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005688 } else if (audio_extn_ffv_get_stream() == in) {
5689 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305690 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005691 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305692 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5693 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5694 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5695 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305696 ret = -EINVAL;
5697 goto exit;
5698 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305699 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305700 ret = -errno;
5701 }
5702 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305703 /* bytes read is always set to bytes for non compress usecases */
5704 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005705 }
5706
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005707 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005708
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005709 /*
5710 * Instead of writing zeroes here, we could trust the hardware
5711 * to always provide zeroes when muted.
5712 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305713 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5714 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005715 memset(buffer, 0, bytes);
5716
5717exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005718 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305719 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005720 pthread_mutex_unlock(&in->lock);
5721
5722 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305723 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305724 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305725 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305726 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305727 in->standby = true;
5728 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305729 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5730 bytes_read = bytes;
5731 memset(buffer, 0, bytes);
5732 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005733 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005734 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305735 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305736 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005737 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305738 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005739}
5740
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005741static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005742{
5743 return 0;
5744}
5745
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005746static int add_remove_audio_effect(const struct audio_stream *stream,
5747 effect_handle_t effect,
5748 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005749{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005750 struct stream_in *in = (struct stream_in *)stream;
5751 int status = 0;
5752 effect_descriptor_t desc;
5753
5754 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005755 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5756
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005757 if (status != 0)
5758 return status;
5759
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005760 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005761 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08005762 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5763 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005764 in->enable_aec != enable &&
5765 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5766 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005767 if (!in->standby) {
5768 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5769 select_devices(in->dev, in->usecase);
5770 }
5771
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005772 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005773 if (in->enable_ns != enable &&
5774 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5775 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005776 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08005777 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5778 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005779 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5780 select_devices(in->dev, in->usecase);
5781 } else
5782 select_devices(in->dev, in->usecase);
5783 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005784 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005785 pthread_mutex_unlock(&in->dev->lock);
5786 pthread_mutex_unlock(&in->lock);
5787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005788 return 0;
5789}
5790
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005791static int in_add_audio_effect(const struct audio_stream *stream,
5792 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005793{
Eric Laurent994a6932013-07-17 11:51:42 -07005794 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005795 return add_remove_audio_effect(stream, effect, true);
5796}
5797
5798static int in_remove_audio_effect(const struct audio_stream *stream,
5799 effect_handle_t effect)
5800{
Eric Laurent994a6932013-07-17 11:51:42 -07005801 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005802 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005803}
5804
Haynes Mathew George16081042017-05-31 17:16:49 -07005805static int in_stop(const struct audio_stream_in* stream)
5806{
5807 struct stream_in *in = (struct stream_in *)stream;
5808 struct audio_device *adev = in->dev;
5809
5810 int ret = -ENOSYS;
5811 ALOGV("%s", __func__);
5812 pthread_mutex_lock(&adev->lock);
5813 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5814 in->capture_started && in->pcm != NULL) {
5815 pcm_stop(in->pcm);
5816 ret = stop_input_stream(in);
5817 in->capture_started = false;
5818 }
5819 pthread_mutex_unlock(&adev->lock);
5820 return ret;
5821}
5822
5823static int in_start(const struct audio_stream_in* stream)
5824{
5825 struct stream_in *in = (struct stream_in *)stream;
5826 struct audio_device *adev = in->dev;
5827 int ret = -ENOSYS;
5828
5829 ALOGV("%s in %p", __func__, in);
5830 pthread_mutex_lock(&adev->lock);
5831 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5832 !in->capture_started && in->pcm != NULL) {
5833 if (!in->capture_started) {
5834 ret = start_input_stream(in);
5835 if (ret == 0) {
5836 in->capture_started = true;
5837 }
5838 }
5839 }
5840 pthread_mutex_unlock(&adev->lock);
5841 return ret;
5842}
5843
5844static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5845 int32_t min_size_frames,
5846 struct audio_mmap_buffer_info *info)
5847{
5848 struct stream_in *in = (struct stream_in *)stream;
5849 struct audio_device *adev = in->dev;
5850 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005851 unsigned int offset1 = 0;
5852 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005853 const char *step = "";
5854
5855 pthread_mutex_lock(&adev->lock);
5856 ALOGV("%s in %p", __func__, in);
5857
Sharad Sanglec6f32552018-05-04 16:15:38 +05305858 if (CARD_STATUS_OFFLINE == in->card_status||
5859 CARD_STATUS_OFFLINE == adev->card_status) {
5860 ALOGW("in->card_status or adev->card_status offline, try again");
5861 ret = -EIO;
5862 goto exit;
5863 }
5864
Haynes Mathew George16081042017-05-31 17:16:49 -07005865 if (info == NULL || min_size_frames == 0) {
5866 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5867 ret = -EINVAL;
5868 goto exit;
5869 }
5870 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5871 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5872 ALOGV("%s in %p", __func__, in);
5873 ret = -ENOSYS;
5874 goto exit;
5875 }
5876 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5877 if (in->pcm_device_id < 0) {
5878 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5879 __func__, in->pcm_device_id, in->usecase);
5880 ret = -EINVAL;
5881 goto exit;
5882 }
5883
5884 adjust_mmap_period_count(&in->config, min_size_frames);
5885
5886 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5887 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5888 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5889 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305890 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305891 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5892 in->card_status = CARD_STATUS_OFFLINE;
5893 adev->card_status = CARD_STATUS_OFFLINE;
5894 ret = -EIO;
5895 goto exit;
5896 }
5897
Haynes Mathew George16081042017-05-31 17:16:49 -07005898 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5899 step = "open";
5900 ret = -ENODEV;
5901 goto exit;
5902 }
5903
5904 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5905 if (ret < 0) {
5906 step = "begin";
5907 goto exit;
5908 }
5909 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5910 info->burst_size_frames = in->config.period_size;
5911 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
5912
5913 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
5914 info->buffer_size_frames));
5915
5916 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
5917 if (ret < 0) {
5918 step = "commit";
5919 goto exit;
5920 }
5921
5922 in->standby = false;
5923 ret = 0;
5924
5925 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5926 __func__, info->shared_memory_address, info->buffer_size_frames);
5927
5928exit:
5929 if (ret != 0) {
5930 if (in->pcm == NULL) {
5931 ALOGE("%s: %s - %d", __func__, step, ret);
5932 } else {
5933 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
5934 pcm_close(in->pcm);
5935 in->pcm = NULL;
5936 }
5937 }
5938 pthread_mutex_unlock(&adev->lock);
5939 return ret;
5940}
5941
5942static int in_get_mmap_position(const struct audio_stream_in *stream,
5943 struct audio_mmap_position *position)
5944{
5945 struct stream_in *in = (struct stream_in *)stream;
5946 ALOGVV("%s", __func__);
5947 if (position == NULL) {
5948 return -EINVAL;
5949 }
5950 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
5951 return -ENOSYS;
5952 }
5953 if (in->pcm == NULL) {
5954 return -ENOSYS;
5955 }
5956 struct timespec ts = { 0, 0 };
5957 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
5958 if (ret < 0) {
5959 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
5960 return ret;
5961 }
Naresh Tanniru119d74a2018-11-02 09:49:44 +05305962 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005963 return 0;
5964}
5965
Naresh Tannirudcb47c52018-06-25 16:23:32 +05305966static int in_get_active_microphones(const struct audio_stream_in *stream,
5967 struct audio_microphone_characteristic_t *mic_array,
5968 size_t *mic_count) {
5969 struct stream_in *in = (struct stream_in *)stream;
5970 struct audio_device *adev = in->dev;
5971 ALOGVV("%s", __func__);
5972
5973 lock_input_stream(in);
5974 pthread_mutex_lock(&adev->lock);
5975 int ret = platform_get_active_microphones(adev->platform,
5976 audio_channel_count_from_in_mask(in->channel_mask),
5977 in->usecase, mic_array, mic_count);
5978 pthread_mutex_unlock(&adev->lock);
5979 pthread_mutex_unlock(&in->lock);
5980
5981 return ret;
5982}
5983
5984static int adev_get_microphones(const struct audio_hw_device *dev,
5985 struct audio_microphone_characteristic_t *mic_array,
5986 size_t *mic_count) {
5987 struct audio_device *adev = (struct audio_device *)dev;
5988 ALOGVV("%s", __func__);
5989
5990 pthread_mutex_lock(&adev->lock);
5991 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
5992 pthread_mutex_unlock(&adev->lock);
5993
5994 return ret;
5995}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305996int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07005997 audio_io_handle_t handle,
5998 audio_devices_t devices,
5999 audio_output_flags_t flags,
6000 struct audio_config *config,
6001 struct audio_stream_out **stream_out,
6002 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006003{
6004 struct audio_device *adev = (struct audio_device *)dev;
6005 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306006 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006007 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006008 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306009 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006010 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6011 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6012 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6013 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006014
kunleizdff872d2018-08-20 14:40:33 +08006015 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006016 is_usb_dev = false;
6017 devices = AUDIO_DEVICE_OUT_SPEAKER;
6018 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6019 __func__, devices);
6020 }
6021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006022 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306023
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006024 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6025
Mingming Yin3a941d42016-02-17 18:08:05 -08006026 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6027 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306028 devices, flags, &out->stream);
6029
6030
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006031 if (!out) {
6032 return -ENOMEM;
6033 }
6034
Haynes Mathew George204045b2015-02-25 20:32:03 -08006035 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006036 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306037 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006038 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006039 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6040
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006041 if (devices == AUDIO_DEVICE_NONE)
6042 devices = AUDIO_DEVICE_OUT_SPEAKER;
6043
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006044 out->flags = flags;
6045 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006046 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006047 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006048 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306049 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306050 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6051 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6052 else
6053 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006054 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006055 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006056 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306057 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306058 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306059 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006060 out->hal_output_suspend_supported = 0;
6061 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05306062 out->set_dual_mono = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006063
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306064 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306065 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006066 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6067
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006068 if (audio_is_linear_pcm(out->format) &&
6069 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
6070 pthread_mutex_lock(&adev->lock);
6071 if (is_hdmi) {
6072 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6073 ret = read_hdmi_sink_caps(out);
6074 } else if (is_usb_dev) {
6075 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6076 &config->format,
6077 &out->supported_formats[0],
6078 MAX_SUPPORTED_FORMATS,
6079 &config->channel_mask,
6080 &out->supported_channel_masks[0],
6081 MAX_SUPPORTED_CHANNEL_MASKS,
6082 &config->sample_rate,
6083 &out->supported_sample_rates[0],
6084 MAX_SUPPORTED_SAMPLE_RATES);
6085 ALOGV("plugged dev USB ret %d", ret);
6086 } else {
6087 ret = -1;
6088 }
6089 pthread_mutex_unlock(&adev->lock);
6090 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006091 if (ret == -ENOSYS) {
6092 /* ignore and go with default */
6093 ret = 0;
6094 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006095 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006096 goto error_open;
6097 }
6098 }
6099 }
6100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006101 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07006102#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006103 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6104 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6105 out->sample_rate == 32000 || out->sample_rate == 48000)) {
6106 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
6107 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
6108 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
6109
6110 out->config = default_pcm_config_voip_copp;
6111 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6112 out->config.rate = out->sample_rate;
6113
6114#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05306115 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006116 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08006117 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006118 ret = voice_extn_compress_voip_open_output_stream(out);
6119 if (ret != 0) {
6120 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6121 __func__, ret);
6122 goto error_open;
6123 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006124#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006125 } else if (audio_is_linear_pcm(out->format) &&
6126 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6127 out->channel_mask = config->channel_mask;
6128 out->sample_rate = config->sample_rate;
6129 out->format = config->format;
6130 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6131 // does this change?
6132 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6133 out->config.rate = config->sample_rate;
6134 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6135 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6136 audio_bytes_per_sample(config->format));
6137 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006138 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306139 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306140 pthread_mutex_lock(&adev->lock);
6141 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6142 pthread_mutex_unlock(&adev->lock);
6143
6144 // reject offload during card offline to allow
6145 // fallback to s/w paths
6146 if (offline) {
6147 ret = -ENODEV;
6148 goto error_open;
6149 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006150
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006151 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6152 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6153 ALOGE("%s: Unsupported Offload information", __func__);
6154 ret = -EINVAL;
6155 goto error_open;
6156 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006157
Atul Khare3fa6e542017-08-09 00:56:17 +05306158 if (config->offload_info.format == 0)
6159 config->offload_info.format = config->format;
6160 if (config->offload_info.sample_rate == 0)
6161 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006162
Mingming Yin90310102013-11-13 16:57:00 -08006163 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306164 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006165 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006166 ret = -EINVAL;
6167 goto error_open;
6168 }
6169
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006170 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6171 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6172 (audio_extn_passthru_is_passthrough_stream(out)) &&
6173 !((config->sample_rate == 48000) ||
6174 (config->sample_rate == 96000) ||
6175 (config->sample_rate == 192000))) {
6176 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6177 __func__, config->sample_rate, config->offload_info.format);
6178 ret = -EINVAL;
6179 goto error_open;
6180 }
6181
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006182 out->compr_config.codec = (struct snd_codec *)
6183 calloc(1, sizeof(struct snd_codec));
6184
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006185 if (!out->compr_config.codec) {
6186 ret = -ENOMEM;
6187 goto error_open;
6188 }
6189
Dhananjay Kumarac341582017-02-23 23:42:25 +05306190 out->stream.pause = out_pause;
6191 out->stream.resume = out_resume;
6192 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306193 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306194 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006195 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306196 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006197 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306198 } else {
6199 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6200 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006201 }
vivek mehta446c3962015-09-14 10:57:35 -07006202
6203 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006204 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6205 config->format == 0 && config->sample_rate == 0 &&
6206 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006207 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006208 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6209 } else {
6210 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6211 ret = -EEXIST;
6212 goto error_open;
6213 }
vivek mehta446c3962015-09-14 10:57:35 -07006214 }
6215
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006216 if (config->offload_info.channel_mask)
6217 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006218 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006219 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006220 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006221 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306222 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006223 ret = -EINVAL;
6224 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006225 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006226
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006227 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006228 out->sample_rate = config->offload_info.sample_rate;
6229
Mingming Yin3ee55c62014-08-04 14:23:35 -07006230 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006231
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306232 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306233 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306234 audio_extn_dolby_send_ddp_endp_params(adev);
6235 audio_extn_dolby_set_dmid(adev);
6236 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006237
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006238 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006239 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006240 out->compr_config.codec->bit_rate =
6241 config->offload_info.bit_rate;
6242 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306243 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006244 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306245 /* Update bit width only for non passthrough usecases.
6246 * For passthrough usecases, the output will always be opened @16 bit
6247 */
6248 if (!audio_extn_passthru_is_passthrough_stream(out))
6249 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306250
6251 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6252 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6253 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6254
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006255 /*TODO: Do we need to change it for passthrough */
6256 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006257
Manish Dewangana6fc5442015-08-24 20:30:31 +05306258 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6259 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306260 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306261 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306262 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6263 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306264
6265 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6266 AUDIO_FORMAT_PCM) {
6267
6268 /*Based on platform support, configure appropriate alsa format for corresponding
6269 *hal input format.
6270 */
6271 out->compr_config.codec->format = hal_format_to_alsa(
6272 config->offload_info.format);
6273
Ashish Jain83a6cc22016-06-28 14:34:17 +05306274 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306275 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306276 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306277
Dhananjay Kumarac341582017-02-23 23:42:25 +05306278 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306279 *hal input format and alsa format might differ based on platform support.
6280 */
6281 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306282 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306283
6284 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6285
6286 /* Check if alsa session is configured with the same format as HAL input format,
6287 * if not then derive correct fragment size needed to accomodate the
6288 * conversion of HAL input format to alsa format.
6289 */
6290 audio_extn_utils_update_direct_pcm_fragment_size(out);
6291
6292 /*if hal input and output fragment size is different this indicates HAL input format is
6293 *not same as the alsa format
6294 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306295 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306296 /*Allocate a buffer to convert input data to the alsa configured format.
6297 *size of convert buffer is equal to the size required to hold one fragment size
6298 *worth of pcm data, this is because flinger does not write more than fragment_size
6299 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306300 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6301 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306302 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6303 ret = -ENOMEM;
6304 goto error_open;
6305 }
6306 }
6307 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6308 out->compr_config.fragment_size =
6309 audio_extn_passthru_get_buffer_size(&config->offload_info);
6310 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6311 } else {
6312 out->compr_config.fragment_size =
6313 platform_get_compress_offload_buffer_size(&config->offload_info);
6314 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6315 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006316
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306317 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6318 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6319 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006320 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306321 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006322
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306323 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6324 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6325 }
6326
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006327 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6328 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006329
Manish Dewangan69426c82017-01-30 17:35:36 +05306330 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6331 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6332 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6333 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6334 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6335 } else {
6336 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6337 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006338
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306339 memset(&out->channel_map_param, 0,
6340 sizeof(struct audio_out_channel_map_param));
6341
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006342 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306343 out->send_next_track_params = false;
6344 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006345 out->offload_state = OFFLOAD_STATE_IDLE;
6346 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006347 out->writeAt.tv_sec = 0;
6348 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006349
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006350 audio_extn_dts_create_state_notifier_node(out->usecase);
6351
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006352 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6353 __func__, config->offload_info.version,
6354 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306355
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306356 /* Check if DSD audio format is supported in codec
6357 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306358 */
6359
6360 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306361 (!platform_check_codec_dsd_support(adev->platform) ||
6362 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306363 ret = -EINVAL;
6364 goto error_open;
6365 }
6366
Ashish Jain5106d362016-05-11 19:23:33 +05306367 /* Disable gapless if any of the following is true
6368 * passthrough playback
6369 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306370 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306371 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306372 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306373 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006374 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306375 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306376 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306377 check_and_set_gapless_mode(adev, false);
6378 } else
6379 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006380
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306381 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006382 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6383 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306384 if (config->format == AUDIO_FORMAT_DSD) {
6385 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6386 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6387 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006388
6389 create_offload_callback_thread(out);
6390
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006391 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006392 switch (config->sample_rate) {
6393 case 0:
6394 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6395 break;
6396 case 8000:
6397 case 16000:
6398 case 48000:
6399 out->sample_rate = config->sample_rate;
6400 break;
6401 default:
6402 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
6403 config->sample_rate);
6404 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6405 ret = -EINVAL;
6406 goto error_open;
6407 }
6408 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6409 switch (config->channel_mask) {
6410 case AUDIO_CHANNEL_NONE:
6411 case AUDIO_CHANNEL_OUT_STEREO:
6412 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6413 break;
6414 default:
6415 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
6416 config->channel_mask);
6417 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6418 ret = -EINVAL;
6419 goto error_open;
6420 }
6421 switch (config->format) {
6422 case AUDIO_FORMAT_DEFAULT:
6423 case AUDIO_FORMAT_PCM_16_BIT:
6424 out->format = AUDIO_FORMAT_PCM_16_BIT;
6425 break;
6426 default:
6427 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
6428 config->format);
6429 config->format = AUDIO_FORMAT_PCM_16_BIT;
6430 ret = -EINVAL;
6431 goto error_open;
6432 }
6433
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306434 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006435 if (ret != 0) {
6436 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006437 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006438 goto error_open;
6439 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006440 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006441 if (config->sample_rate == 0)
6442 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6443 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6444 config->sample_rate != 8000) {
6445 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6446 ret = -EINVAL;
6447 goto error_open;
6448 }
6449 out->sample_rate = config->sample_rate;
6450 out->config.rate = config->sample_rate;
6451 if (config->format == AUDIO_FORMAT_DEFAULT)
6452 config->format = AUDIO_FORMAT_PCM_16_BIT;
6453 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6454 config->format = AUDIO_FORMAT_PCM_16_BIT;
6455 ret = -EINVAL;
6456 goto error_open;
6457 }
6458 out->format = config->format;
6459 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
6460 out->config = pcm_config_afe_proxy_playback;
6461 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006462 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05306463 unsigned int channels = 0;
6464 /*Update config params to default if not set by the caller*/
6465 if (config->sample_rate == 0)
6466 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6467 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6468 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6469 if (config->format == AUDIO_FORMAT_DEFAULT)
6470 config->format = AUDIO_FORMAT_PCM_16_BIT;
6471
6472 channels = audio_channel_count_from_out_mask(out->channel_mask);
6473
Varun Balaraje49253e2017-07-06 19:48:56 +05306474 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6475 out->usecase = get_interactive_usecase(adev);
6476 out->config = pcm_config_low_latency;
6477 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306478 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006479 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6480 out->flags);
6481 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006482 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6483 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6484 out->config = pcm_config_mmap_playback;
6485 out->stream.start = out_start;
6486 out->stream.stop = out_stop;
6487 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6488 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306489 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6490 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006491 out->hal_output_suspend_supported =
6492 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6493 out->dynamic_pm_qos_config_supported =
6494 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6495 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006496 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6497 } else {
6498 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6499 //the mixer path will be a string similar to "low-latency-playback resume"
6500 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6501 strlcat(out->pm_qos_mixer_path,
6502 " resume", MAX_MIXER_PATH_LEN);
6503 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6504 out->pm_qos_mixer_path);
6505 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306506 out->config = pcm_config_low_latency;
6507 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6508 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6509 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306510 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6511 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6512 if (out->config.period_size <= 0) {
6513 ALOGE("Invalid configuration period size is not valid");
6514 ret = -EINVAL;
6515 goto error_open;
6516 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306517 } else {
6518 /* primary path is the default path selected if no other outputs are available/suitable */
6519 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6520 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6521 }
6522 out->hal_ip_format = format = out->format;
6523 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6524 out->hal_op_format = pcm_format_to_hal(out->config.format);
6525 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6526 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006527 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306528 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306529 if (out->hal_ip_format != out->hal_op_format) {
6530 uint32_t buffer_size = out->config.period_size *
6531 format_to_bitwidth_table[out->hal_op_format] *
6532 out->config.channels;
6533 out->convert_buffer = calloc(1, buffer_size);
6534 if (out->convert_buffer == NULL){
6535 ALOGE("Allocation failed for convert buffer for size %d",
6536 out->compr_config.fragment_size);
6537 ret = -ENOMEM;
6538 goto error_open;
6539 }
6540 ALOGD("Convert buffer allocated of size %d", buffer_size);
6541 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006542 }
6543
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006544 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6545 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306546
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006547 /* TODO remove this hardcoding and check why width is zero*/
6548 if (out->bit_width == 0)
6549 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306550 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006551 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006552 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306553 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306554 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006555 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6556 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6557 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006558 if(adev->primary_output == NULL)
6559 adev->primary_output = out;
6560 else {
6561 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006562 ret = -EEXIST;
6563 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006564 }
6565 }
6566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006567 /* Check if this usecase is already existing */
6568 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006569 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6570 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006571 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006572 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006573 ret = -EEXIST;
6574 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006575 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006576
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006577 pthread_mutex_unlock(&adev->lock);
6578
6579 out->stream.common.get_sample_rate = out_get_sample_rate;
6580 out->stream.common.set_sample_rate = out_set_sample_rate;
6581 out->stream.common.get_buffer_size = out_get_buffer_size;
6582 out->stream.common.get_channels = out_get_channels;
6583 out->stream.common.get_format = out_get_format;
6584 out->stream.common.set_format = out_set_format;
6585 out->stream.common.standby = out_standby;
6586 out->stream.common.dump = out_dump;
6587 out->stream.common.set_parameters = out_set_parameters;
6588 out->stream.common.get_parameters = out_get_parameters;
6589 out->stream.common.add_audio_effect = out_add_audio_effect;
6590 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6591 out->stream.get_latency = out_get_latency;
6592 out->stream.set_volume = out_set_volume;
6593 out->stream.write = out_write;
6594 out->stream.get_render_position = out_get_render_position;
6595 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006596 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006597
Haynes Mathew George16081042017-05-31 17:16:49 -07006598 if (out->realtime)
6599 out->af_period_multiplier = af_period_multiplier;
6600 else
6601 out->af_period_multiplier = 1;
6602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006603 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006604 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006605 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006606
6607 config->format = out->stream.common.get_format(&out->stream.common);
6608 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6609 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05306610 register_format(out->format, out->supported_formats);
6611 register_channel_mask(out->channel_mask, out->supported_channel_masks);
6612 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006613
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306614 /*
6615 By locking output stream before registering, we allow the callback
6616 to update stream's state only after stream's initial state is set to
6617 adev state.
6618 */
6619 lock_output_stream(out);
6620 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6621 pthread_mutex_lock(&adev->lock);
6622 out->card_status = adev->card_status;
6623 pthread_mutex_unlock(&adev->lock);
6624 pthread_mutex_unlock(&out->lock);
6625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006626 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306627 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006628 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006629
6630 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6631 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6632 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006633 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306634 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006635 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006636 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306637 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006638 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6639 out->usecase, PCM_PLAYBACK);
6640 hdlr_stream_cfg.flags = out->flags;
6641 hdlr_stream_cfg.type = PCM_PLAYBACK;
6642 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6643 &hdlr_stream_cfg);
6644 if (ret) {
6645 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6646 out->adsp_hdlr_stream_handle = NULL;
6647 }
6648 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306649 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006650 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006651 if (ret < 0) {
6652 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6653 out->ip_hdlr_handle = NULL;
6654 }
6655 }
Eric Laurent994a6932013-07-17 11:51:42 -07006656 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006657 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006658
6659error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306660 if (out->convert_buffer)
6661 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006662 free(out);
6663 *stream_out = NULL;
6664 ALOGD("%s: exit: ret %d", __func__, ret);
6665 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006666}
6667
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306668void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006669 struct audio_stream_out *stream)
6670{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006671 struct stream_out *out = (struct stream_out *)stream;
6672 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006673 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006674
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006675 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306676
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306677 // must deregister from sndmonitor first to prevent races
6678 // between the callback and close_stream
6679 audio_extn_snd_mon_unregister_listener(out);
6680
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006681 /* close adsp hdrl session before standby */
6682 if (out->adsp_hdlr_stream_handle) {
6683 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6684 if (ret)
6685 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6686 out->adsp_hdlr_stream_handle = NULL;
6687 }
6688
Manish Dewangan21a850a2017-08-14 12:03:55 +05306689 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006690 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6691 out->ip_hdlr_handle = NULL;
6692 }
6693
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006694 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306695 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006696 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306697 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306698 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006699 if(ret != 0)
6700 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6701 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006702 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006703 out_standby(&stream->common);
6704
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006705 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006706 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006707 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006708 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006709 if (out->compr_config.codec != NULL)
6710 free(out->compr_config.codec);
6711 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006712
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306713 out->a2dp_compress_mute = false;
6714
Varun Balaraje49253e2017-07-06 19:48:56 +05306715 if (is_interactive_usecase(out->usecase))
6716 free_interactive_usecase(adev, out->usecase);
6717
Ashish Jain83a6cc22016-06-28 14:34:17 +05306718 if (out->convert_buffer != NULL) {
6719 free(out->convert_buffer);
6720 out->convert_buffer = NULL;
6721 }
6722
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006723 if (adev->voice_tx_output == out)
6724 adev->voice_tx_output = NULL;
6725
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306726 if (adev->primary_output == out)
6727 adev->primary_output = NULL;
6728
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006729 pthread_cond_destroy(&out->cond);
6730 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006731 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006732 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006733}
6734
6735static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6736{
6737 struct audio_device *adev = (struct audio_device *)dev;
6738 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006739 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006740 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006741 int ret;
6742 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006743
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006744 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006745 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006746
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306747 if (!parms)
6748 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306749
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306750 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6751 if (ret >= 0) {
6752 /* When set to false, HAL should disable EC and NS */
6753 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6754 adev->bt_sco_on = true;
6755 else
6756 adev->bt_sco_on = false;
6757 }
6758
Naresh Tanniru4c630392014-05-12 01:05:52 +05306759 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006760 status = voice_set_parameters(adev, parms);
6761 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006762 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006763
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006764 status = platform_set_parameters(adev->platform, parms);
6765 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006766 goto done;
6767
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006768 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6769 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006770 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006771 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6772 adev->bluetooth_nrec = true;
6773 else
6774 adev->bluetooth_nrec = false;
6775 }
6776
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006777 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6778 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006779 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6780 adev->screen_off = false;
6781 else
6782 adev->screen_off = true;
6783 }
6784
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006785 ret = str_parms_get_int(parms, "rotation", &val);
6786 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006787 bool reverse_speakers = false;
6788 switch(val) {
6789 // FIXME: note that the code below assumes that the speakers are in the correct placement
6790 // relative to the user when the device is rotated 90deg from its default rotation. This
6791 // assumption is device-specific, not platform-specific like this code.
6792 case 270:
6793 reverse_speakers = true;
6794 break;
6795 case 0:
6796 case 90:
6797 case 180:
6798 break;
6799 default:
6800 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006801 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006802 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006803 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006804 // check and set swap
6805 // - check if orientation changed and speaker active
6806 // - set rotation and cache the rotation value
6807 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006808 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006809 }
6810
Mingming Yin514a8bc2014-07-29 15:22:21 -07006811 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6812 if (ret >= 0) {
6813 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6814 adev->bt_wb_speech_enabled = true;
6815 else
6816 adev->bt_wb_speech_enabled = false;
6817 }
6818
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006819 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6820 if (ret >= 0) {
6821 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306822 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08006823 if (audio_is_output_device(val) &&
6824 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006825 ALOGV("cache new ext disp type and edid");
6826 ret = platform_get_ext_disp_type(adev->platform);
6827 if (ret < 0) {
6828 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05306829 } else {
6830 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006831 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306832 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07006833 /*
6834 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6835 * Per AudioPolicyManager, USB device is higher priority than WFD.
6836 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6837 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6838 * starting voice call on USB
6839 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006840 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306841 if (ret >= 0)
6842 audio_extn_usb_add_device(device, atoi(value));
6843
Zhou Song6f862822017-11-06 17:27:57 +08006844 if (!audio_extn_usb_is_tunnel_supported()) {
6845 ALOGV("detected USB connect .. disable proxy");
6846 adev->allow_afe_proxy_usage = false;
6847 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006848 }
6849 }
6850
6851 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6852 if (ret >= 0) {
6853 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306854 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07006855 /*
6856 * The HDMI / Displayport disconnect handling has been moved to
6857 * audio extension to ensure that its parameters are not
6858 * invalidated prior to updating sysfs of the disconnect event
6859 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6860 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306861 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006862 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306863 if (ret >= 0)
6864 audio_extn_usb_remove_device(device, atoi(value));
6865
Zhou Song6f862822017-11-06 17:27:57 +08006866 if (!audio_extn_usb_is_tunnel_supported()) {
6867 ALOGV("detected USB disconnect .. enable proxy");
6868 adev->allow_afe_proxy_usage = true;
6869 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006870 }
6871 }
6872
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306873 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6874 if (ret >= 0) {
6875 struct audio_usecase *usecase;
6876 struct listnode *node;
6877 list_for_each(node, &adev->usecase_list) {
6878 usecase = node_to_item(node, struct audio_usecase, list);
6879 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07006880 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306881 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08006882
6883 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306884 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08006885 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306886 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306887 //force device switch to re configure encoder
6888 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306889 audio_extn_a2dp_set_handoff_mode(false);
6890 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306891 break;
6892 }
6893 }
6894 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006895
6896 //handle vr audio setparam
6897 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6898 value, sizeof(value));
6899 if (ret >= 0) {
6900 ALOGI("Setting vr mode to be %s", value);
6901 if (!strncmp(value, "true", 4)) {
6902 adev->vr_audio_mode_enabled = true;
6903 ALOGI("Setting vr mode to true");
6904 } else if (!strncmp(value, "false", 5)) {
6905 adev->vr_audio_mode_enabled = false;
6906 ALOGI("Setting vr mode to false");
6907 } else {
6908 ALOGI("wrong vr mode set");
6909 }
6910 }
6911
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306912 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006913done:
6914 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006915 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306916error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006917 ALOGV("%s: exit with code(%d)", __func__, status);
6918 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006919}
6920
6921static char* adev_get_parameters(const struct audio_hw_device *dev,
6922 const char *keys)
6923{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006924 struct audio_device *adev = (struct audio_device *)dev;
6925 struct str_parms *reply = str_parms_create();
6926 struct str_parms *query = str_parms_create_str(keys);
6927 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05306928 char value[256] = {0};
6929 int ret = 0;
6930
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006931 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006932 if (reply) {
6933 str_parms_destroy(reply);
6934 }
6935 if (query) {
6936 str_parms_destroy(query);
6937 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006938 ALOGE("adev_get_parameters: failed to create query or reply");
6939 return NULL;
6940 }
6941
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006942 //handle vr audio getparam
6943
6944 ret = str_parms_get_str(query,
6945 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6946 value, sizeof(value));
6947
6948 if (ret >= 0) {
6949 bool vr_audio_enabled = false;
6950 pthread_mutex_lock(&adev->lock);
6951 vr_audio_enabled = adev->vr_audio_mode_enabled;
6952 pthread_mutex_unlock(&adev->lock);
6953
6954 ALOGI("getting vr mode to %d", vr_audio_enabled);
6955
6956 if (vr_audio_enabled) {
6957 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6958 "true");
6959 goto exit;
6960 } else {
6961 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6962 "false");
6963 goto exit;
6964 }
6965 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006966
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006967 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006968 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08006969 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006970 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05306971 pthread_mutex_unlock(&adev->lock);
6972
Naresh Tannirud7205b62014-06-20 02:54:48 +05306973exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006974 str = str_parms_to_str(reply);
6975 str_parms_destroy(query);
6976 str_parms_destroy(reply);
6977
6978 ALOGV("%s: exit: returns - %s", __func__, str);
6979 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006980}
6981
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006982static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006983{
6984 return 0;
6985}
6986
6987static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
6988{
Haynes Mathew George5191a852013-09-11 14:19:36 -07006989 int ret;
6990 struct audio_device *adev = (struct audio_device *)dev;
6991 pthread_mutex_lock(&adev->lock);
6992 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07006993 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07006994 pthread_mutex_unlock(&adev->lock);
6995 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006996}
6997
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006998static int adev_set_master_volume(struct audio_hw_device *dev __unused,
6999 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007000{
7001 return -ENOSYS;
7002}
7003
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007004static int adev_get_master_volume(struct audio_hw_device *dev __unused,
7005 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007006{
7007 return -ENOSYS;
7008}
7009
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007010static int adev_set_master_mute(struct audio_hw_device *dev __unused,
7011 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007012{
7013 return -ENOSYS;
7014}
7015
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007016static int adev_get_master_mute(struct audio_hw_device *dev __unused,
7017 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007018{
7019 return -ENOSYS;
7020}
7021
7022static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
7023{
7024 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07007025 struct listnode *node;
7026 struct audio_usecase *usecase = NULL;
7027 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007028 pthread_mutex_lock(&adev->lock);
7029 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007030 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007031 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08007032 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07007033 list_for_each(node, &adev->usecase_list) {
7034 usecase = node_to_item(node, struct audio_usecase, list);
7035 if (usecase->type == VOICE_CALL)
7036 break;
7037 }
7038 if (usecase &&
7039 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
7040 ret = audio_extn_usb_check_and_set_svc_int(usecase,
7041 true);
7042 if (ret != 0) {
7043 /* default service interval was successfully updated,
7044 reopen USB backend with new service interval */
7045 check_usecases_codec_backend(adev,
7046 usecase,
7047 usecase->out_snd_device);
7048 }
7049 }
7050
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007051 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07007052 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007053 adev->current_call_output = NULL;
7054 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007055 }
7056 pthread_mutex_unlock(&adev->lock);
7057 return 0;
7058}
7059
7060static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
7061{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007062 int ret;
7063
7064 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08007065 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007066 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Derek Chend2530072014-11-24 12:39:14 -08007067 if (adev->ext_hw_plugin)
7068 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007069 pthread_mutex_unlock(&adev->lock);
7070
7071 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007072}
7073
7074static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
7075{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007076 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007077 return 0;
7078}
7079
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007080static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007081 const struct audio_config *config)
7082{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007083 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007084
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007085 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
7086 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007087}
7088
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007089static bool adev_input_allow_hifi_record(struct audio_device *adev,
7090 audio_devices_t devices,
7091 audio_input_flags_t flags,
7092 audio_source_t source) {
7093 const bool allowed = true;
7094
7095 if (!audio_is_usb_in_device(devices))
7096 return !allowed;
7097
7098 switch (flags) {
7099 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007100 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07007101 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7102 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007103 default:
7104 return !allowed;
7105 }
7106
7107 switch (source) {
7108 case AUDIO_SOURCE_DEFAULT:
7109 case AUDIO_SOURCE_MIC:
7110 case AUDIO_SOURCE_UNPROCESSED:
7111 break;
7112 default:
7113 return !allowed;
7114 }
7115
7116 switch (adev->mode) {
7117 case 0:
7118 break;
7119 default:
7120 return !allowed;
7121 }
7122
7123 return allowed;
7124}
7125
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007126static int adev_update_voice_comm_input_stream(struct stream_in *in,
7127 struct audio_config *config)
7128{
7129 bool valid_rate = (config->sample_rate == 8000 ||
7130 config->sample_rate == 16000 ||
7131 config->sample_rate == 32000 ||
7132 config->sample_rate == 48000);
7133 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
7134
7135#ifndef COMPRESS_VOIP_ENABLED
kunleizd96526c2018-04-09 11:12:32 +08007136 if (valid_rate && valid_ch &&
7137 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007138 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7139 in->config = default_pcm_config_voip_copp;
7140 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
7141 DEFAULT_VOIP_BUF_DURATION_MS,
7142 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
7143 } else {
kunleizbdd9ad02018-04-24 10:53:17 +08007144 ALOGW("%s No valid input in voip, use defaults"
7145 "sample rate %u, channel mask 0x%X",
7146 __func__, config->sample_rate, in->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007147 }
7148 in->config.rate = config->sample_rate;
7149 in->sample_rate = config->sample_rate;
7150#else
7151 //XXX needed for voice_extn_compress_voip_open_input_stream
7152 in->config.rate = config->sample_rate;
7153 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7154 voice_extn_compress_voip_is_active(in->dev)) &&
7155 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7156 valid_rate && valid_ch) {
7157 voice_extn_compress_voip_open_input_stream(in);
7158 // update rate entries to match config from AF
7159 in->config.rate = config->sample_rate;
7160 in->sample_rate = config->sample_rate;
7161 } else {
7162 ALOGW("%s compress voip not active, use defaults", __func__);
7163 }
7164#endif
7165 return 0;
7166}
7167
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007168static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007169 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007170 audio_devices_t devices,
7171 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007172 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307173 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007174 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007175 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007176{
7177 struct audio_device *adev = (struct audio_device *)dev;
7178 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007179 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007180 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007181 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05307182 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007183 bool is_usb_dev = audio_is_usb_in_device(devices);
7184 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
7185 devices,
7186 flags,
7187 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307188
kunleizdff872d2018-08-20 14:40:33 +08007189 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007190 is_usb_dev = false;
7191 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
7192 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
7193 __func__, devices);
7194 }
7195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007196 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007197
7198 if (!(is_usb_dev && may_use_hifi_record)) {
7199 if (config->sample_rate == 0)
7200 config->sample_rate = 48000;
7201 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7202 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7203 if (config->format == AUDIO_FORMAT_DEFAULT)
7204 config->format = AUDIO_FORMAT_PCM_16_BIT;
7205
7206 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
7207
7208 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
7209 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05307210 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007211
7212 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007213
7214 if (!in) {
7215 ALOGE("failed to allocate input stream");
7216 return -ENOMEM;
7217 }
7218
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307219 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307220 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7221 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007222 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007223 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007224
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007225 in->stream.common.get_sample_rate = in_get_sample_rate;
7226 in->stream.common.set_sample_rate = in_set_sample_rate;
7227 in->stream.common.get_buffer_size = in_get_buffer_size;
7228 in->stream.common.get_channels = in_get_channels;
7229 in->stream.common.get_format = in_get_format;
7230 in->stream.common.set_format = in_set_format;
7231 in->stream.common.standby = in_standby;
7232 in->stream.common.dump = in_dump;
7233 in->stream.common.set_parameters = in_set_parameters;
7234 in->stream.common.get_parameters = in_get_parameters;
7235 in->stream.common.add_audio_effect = in_add_audio_effect;
7236 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7237 in->stream.set_gain = in_set_gain;
7238 in->stream.read = in_read;
7239 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307240 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007241
7242 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007243 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007244 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007245 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007246 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007247 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007248 in->bit_width = 16;
7249 in->af_period_multiplier = 1;
7250
7251 /* Update config params with the requested sample rate and channels */
7252 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
7253 (adev->mode != AUDIO_MODE_IN_CALL)) {
7254 ret = -EINVAL;
7255 goto err_open;
7256 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007257
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007258 if (is_usb_dev && may_use_hifi_record) {
7259 /* HiFi record selects an appropriate format, channel, rate combo
7260 depending on sink capabilities*/
7261 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7262 &config->format,
7263 &in->supported_formats[0],
7264 MAX_SUPPORTED_FORMATS,
7265 &config->channel_mask,
7266 &in->supported_channel_masks[0],
7267 MAX_SUPPORTED_CHANNEL_MASKS,
7268 &config->sample_rate,
7269 &in->supported_sample_rates[0],
7270 MAX_SUPPORTED_SAMPLE_RATES);
7271 if (ret != 0) {
7272 ret = -EINVAL;
7273 goto err_open;
7274 }
7275 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007276 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307277 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05307278 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
7279 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
7280 in->config.format = PCM_FORMAT_S32_LE;
7281 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307282 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
7283 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
7284 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
7285 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7286 bool ret_error = false;
7287 in->bit_width = 24;
7288 /* 24 bit is restricted to UNPROCESSED source only,also format supported
7289 from HAL is 24_packed and 8_24
7290 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
7291 24_packed return error indicating supported format is 24_packed
7292 *> In case of any other source requesting 24 bit or float return error
7293 indicating format supported is 16 bit only.
7294
7295 on error flinger will retry with supported format passed
7296 */
7297 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
7298 (source != AUDIO_SOURCE_CAMCORDER)) {
7299 config->format = AUDIO_FORMAT_PCM_16_BIT;
7300 if (config->sample_rate > 48000)
7301 config->sample_rate = 48000;
7302 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07007303 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
7304 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307305 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
7306 ret_error = true;
7307 }
7308
7309 if (ret_error) {
7310 ret = -EINVAL;
7311 goto err_open;
7312 }
7313 }
7314
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007315 in->channel_mask = config->channel_mask;
7316 in->format = config->format;
7317
7318 in->usecase = USECASE_AUDIO_RECORD;
7319 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
7320 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
7321 is_low_latency = true;
7322#if LOW_LATENCY_CAPTURE_USE_CASE
7323 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
7324#endif
7325 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
7326 }
7327
7328 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
7329 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
7330 in->realtime = 0;
7331 in->usecase = USECASE_AUDIO_RECORD_MMAP;
7332 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07007333 in->config.format = pcm_format_from_audio_format(config->format);
Weiyin Jiang7c30c612018-11-27 18:45:53 +08007334 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007335 in->stream.start = in_start;
7336 in->stream.stop = in_stop;
7337 in->stream.create_mmap_buffer = in_create_mmap_buffer;
7338 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007339 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007340 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
7341 } else if (in->realtime) {
7342 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07007343 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007344 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007345 in->sample_rate = in->config.rate;
7346 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07007347 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007348 in->usecase = USECASE_AUDIO_RECORD_HIFI;
7349 in->config = pcm_config_audio_capture;
7350 frame_size = audio_stream_in_frame_size(&in->stream);
7351 buffer_size = get_input_buffer_size(config->sample_rate,
7352 config->format,
7353 channel_count,
7354 false /*is_low_latency*/);
7355 in->config.period_size = buffer_size / frame_size;
7356 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007357 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07007358 switch (config->format) {
7359 case AUDIO_FORMAT_PCM_32_BIT:
7360 in->bit_width = 32;
7361 break;
7362 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
7363 case AUDIO_FORMAT_PCM_8_24_BIT:
7364 in->bit_width = 24;
7365 break;
7366 default:
7367 in->bit_width = 16;
7368 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007369 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007370 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007371 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05307372 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007373 if (config->sample_rate == 0)
7374 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7375 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
7376 config->sample_rate != 8000) {
7377 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7378 ret = -EINVAL;
7379 goto err_open;
7380 }
7381 if (config->format == AUDIO_FORMAT_DEFAULT)
7382 config->format = AUDIO_FORMAT_PCM_16_BIT;
7383 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
7384 config->format = AUDIO_FORMAT_PCM_16_BIT;
7385 ret = -EINVAL;
7386 goto err_open;
7387 }
7388
7389 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
7390 in->config = pcm_config_afe_proxy_record;
7391 in->config.channels = channel_count;
7392 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307393 in->sample_rate = config->sample_rate;
Haynes Mathew George46740472017-10-27 18:40:12 -07007394 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05307395 int ret_val;
7396 pthread_mutex_lock(&adev->lock);
7397 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
7398 in, config, &channel_mask_updated);
7399 pthread_mutex_unlock(&adev->lock);
7400
7401 if (!ret_val) {
7402 if (channel_mask_updated == true) {
7403 ALOGD("%s: return error to retry with updated channel mask (%#x)",
7404 __func__, config->channel_mask);
7405 ret = -EINVAL;
7406 goto err_open;
7407 }
7408 ALOGD("%s: created multi-channel session succesfully",__func__);
7409 } else if (audio_extn_compr_cap_enabled() &&
7410 audio_extn_compr_cap_format_supported(config->format) &&
7411 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
7412 audio_extn_compr_cap_init(in);
7413 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05307414 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05307415 ret = audio_extn_cin_configure_input_stream(in);
7416 if (ret)
7417 goto err_open;
7418 } else {
7419 in->config = pcm_config_audio_capture;
7420 in->config.rate = config->sample_rate;
7421 in->config.format = pcm_format_from_audio_format(config->format);
7422 in->config.channels = channel_count;
7423 in->sample_rate = config->sample_rate;
7424 in->format = config->format;
7425 frame_size = audio_stream_in_frame_size(&in->stream);
7426 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07007427 config->format,
7428 channel_count,
7429 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02007430 /* prevent division-by-zero */
7431 if (frame_size == 0) {
7432 ALOGE("%s: Error frame_size==0", __func__);
7433 ret = -EINVAL;
7434 goto err_open;
7435 }
7436
Revathi Uddarajud2634032017-12-07 14:42:34 +05307437 in->config.period_size = buffer_size / frame_size;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007438
Revathi Uddarajud2634032017-12-07 14:42:34 +05307439 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
7440 /* optionally use VOIP usecase depending on config(s) */
7441 ret = adev_update_voice_comm_input_stream(in, config);
7442 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007443
Revathi Uddarajud2634032017-12-07 14:42:34 +05307444 if (ret) {
7445 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
7446 goto err_open;
7447 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007448 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007449 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307450 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7451 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007452 devices, flags, in->format,
7453 in->sample_rate, in->bit_width,
7454 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307455 register_format(in->format, in->supported_formats);
7456 register_channel_mask(in->channel_mask, in->supported_channel_masks);
7457 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307458
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007459 /* This stream could be for sound trigger lab,
7460 get sound trigger pcm if present */
7461 audio_extn_sound_trigger_check_and_get_session(in);
7462
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307463 lock_input_stream(in);
7464 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
7465 pthread_mutex_lock(&adev->lock);
7466 in->card_status = adev->card_status;
7467 pthread_mutex_unlock(&adev->lock);
7468 pthread_mutex_unlock(&in->lock);
7469
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007470 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07007471 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007472 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007473
7474err_open:
7475 free(in);
7476 *stream_in = NULL;
7477 return ret;
7478}
7479
7480static void adev_close_input_stream(struct audio_hw_device *dev,
7481 struct audio_stream_in *stream)
7482{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007483 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007484 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007485 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307486
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307487 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007488
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307489 // must deregister from sndmonitor first to prevent races
7490 // between the callback and close_stream
7491 audio_extn_snd_mon_unregister_listener(stream);
7492
kunleiz8c93ce62018-11-29 15:04:56 +08007493 // Disable echo reference if there are no active input and hfp call
7494 // while closing input stream
7495 if (!adev->active_input && !audio_extn_hfp_is_active(adev))
7496 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307497
Pallavid7c7a272018-01-16 11:22:55 +05307498 if (in == NULL) {
7499 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
7500 return;
7501 }
7502
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007503 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307504 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007505 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307506 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007507 if (ret != 0)
7508 ALOGE("%s: Compress voip input cannot be closed, error:%d",
7509 __func__, ret);
7510 } else
7511 in_standby(&stream->common);
7512
Revathi Uddarajud2634032017-12-07 14:42:34 +05307513 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07007514 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007515 audio_extn_ssr_deinit();
7516 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007517
Garmond Leunge2433c32017-09-28 21:51:22 -07007518 if (audio_extn_ffv_get_stream() == in) {
7519 audio_extn_ffv_stream_deinit();
7520 }
7521
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307522 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07007523 audio_extn_compr_cap_format_supported(in->config.format))
7524 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05307525
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307526 if (audio_extn_cin_attached_usecase(in->usecase))
7527 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007528
Mingming Yinfd7607b2016-01-22 12:48:44 -08007529 if (in->is_st_session) {
7530 ALOGV("%s: sound trigger pcm stop lab", __func__);
7531 audio_extn_sound_trigger_stop_lab(in);
7532 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007533 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307534 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007535 return;
7536}
7537
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307538int adev_create_audio_patch(struct audio_hw_device *dev,
7539 unsigned int num_sources,
7540 const struct audio_port_config *sources,
7541 unsigned int num_sinks,
7542 const struct audio_port_config *sinks,
7543 audio_patch_handle_t *handle)
7544{
7545
7546
7547 return audio_extn_hw_loopback_create_audio_patch(dev,
7548 num_sources,
7549 sources,
7550 num_sinks,
7551 sinks,
7552 handle);
7553
7554}
7555
7556int adev_release_audio_patch(struct audio_hw_device *dev,
7557 audio_patch_handle_t handle)
7558{
7559 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
7560}
7561
7562int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
7563{
7564 return audio_extn_hw_loopback_get_audio_port(dev, config);
7565}
7566
7567int adev_set_audio_port_config(struct audio_hw_device *dev,
7568 const struct audio_port_config *config)
7569{
7570 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
7571}
7572
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007573static int adev_dump(const audio_hw_device_t *device __unused,
7574 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007575{
7576 return 0;
7577}
7578
7579static int adev_close(hw_device_t *device)
7580{
7581 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07007582
7583 if (!adev)
7584 return 0;
7585
7586 pthread_mutex_lock(&adev_init_lock);
7587
7588 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307589 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007590 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08007591 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307592 audio_extn_utils_release_streams_cfg_lists(
7593 &adev->streams_output_cfg_list,
7594 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307595 if (audio_extn_qaf_is_enabled())
7596 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007597 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007598 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007599 free(adev->snd_dev_ref_cnt);
7600 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007601 if (adev->adm_deinit)
7602 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307603 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007604 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307605 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307606 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007607 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307608 if (adev->device_cfg_params) {
7609 free(adev->device_cfg_params);
7610 adev->device_cfg_params = NULL;
7611 }
Derek Chend2530072014-11-24 12:39:14 -08007612 if(adev->ext_hw_plugin)
7613 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Kiran Kandi910e1862013-10-29 13:29:42 -07007614 free(device);
7615 adev = NULL;
7616 }
7617 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05307618 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007619 return 0;
7620}
7621
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007622/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
7623 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
7624 * just that it _might_ work.
7625 */
7626static int period_size_is_plausible_for_low_latency(int period_size)
7627{
7628 switch (period_size) {
7629 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07007630 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007631 case 240:
7632 case 320:
7633 case 480:
7634 return 1;
7635 default:
7636 return 0;
7637 }
7638}
7639
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307640static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
7641{
7642 bool is_snd_card_status = false;
7643 bool is_ext_device_status = false;
7644 char value[32];
7645 int card = -1;
7646 card_status_t status;
7647
7648 if (cookie != adev || !parms)
7649 return;
7650
7651 if (!parse_snd_card_status(parms, &card, &status)) {
7652 is_snd_card_status = true;
7653 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
7654 is_ext_device_status = true;
7655 } else {
7656 // not a valid event
7657 return;
7658 }
7659
7660 pthread_mutex_lock(&adev->lock);
7661 if (card == adev->snd_card || is_ext_device_status) {
7662 if (is_snd_card_status && adev->card_status != status) {
7663 adev->card_status = status;
7664 platform_snd_card_update(adev->platform, status);
7665 audio_extn_fm_set_parameters(adev, parms);
7666 } else if (is_ext_device_status) {
7667 platform_set_parameters(adev->platform, parms);
7668 }
7669 }
7670 pthread_mutex_unlock(&adev->lock);
7671 return;
7672}
7673
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307674/* out and adev lock held */
7675static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
7676{
7677 struct audio_usecase *uc_info;
7678 float left_p;
7679 float right_p;
7680 audio_devices_t devices;
7681
7682 uc_info = get_usecase_from_list(adev, out->usecase);
7683 if (uc_info == NULL) {
7684 ALOGE("%s: Could not find the usecase (%d) in the list",
7685 __func__, out->usecase);
7686 return -EINVAL;
7687 }
7688
7689 ALOGD("%s: enter: usecase(%d: %s)", __func__,
7690 out->usecase, use_case_table[out->usecase]);
7691
7692 if (restore) {
7693 // restore A2DP device for active usecases and unmute if required
7694 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
7695 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
7696 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
7697 select_devices(adev, uc_info->id);
7698 pthread_mutex_lock(&out->compr_mute_lock);
7699 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7700 (out->a2dp_compress_mute)) {
7701 out->a2dp_compress_mute = false;
7702 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
7703 }
7704 pthread_mutex_unlock(&out->compr_mute_lock);
7705 }
7706 } else {
7707 // mute compress stream if suspended
7708 pthread_mutex_lock(&out->compr_mute_lock);
7709 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7710 (!out->a2dp_compress_mute)) {
7711 if (!out->standby) {
7712 ALOGD("%s: selecting speaker and muting stream", __func__);
7713 devices = out->devices;
7714 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
7715 left_p = out->volume_l;
7716 right_p = out->volume_r;
7717 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7718 compress_pause(out->compr);
7719 out_set_compr_volume(&out->stream, (float)0, (float)0);
7720 out->a2dp_compress_mute = true;
7721 select_devices(adev, out->usecase);
7722 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7723 compress_resume(out->compr);
7724 out->devices = devices;
7725 out->volume_l = left_p;
7726 out->volume_r = right_p;
7727 }
7728 }
7729 pthread_mutex_unlock(&out->compr_mute_lock);
7730 }
7731 ALOGV("%s: exit", __func__);
7732 return 0;
7733}
7734
7735int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
7736{
7737 int ret = 0;
7738
7739 lock_output_stream(out);
7740 pthread_mutex_lock(&adev->lock);
7741
7742 ret = check_a2dp_restore_l(adev, out, restore);
7743
7744 pthread_mutex_unlock(&adev->lock);
7745 pthread_mutex_unlock(&out->lock);
7746 return ret;
7747}
7748
Haynes Mathew George01156f92018-04-13 15:29:54 -07007749void adev_on_battery_status_changed(bool charging)
7750{
7751 pthread_mutex_lock(&adev->lock);
7752 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
7753 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08007754 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07007755 pthread_mutex_unlock(&adev->lock);
7756}
7757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007758static int adev_open(const hw_module_t *module, const char *name,
7759 hw_device_t **device)
7760{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307761 int ret;
7762
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007763 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007764 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
7765
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007766 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07007767 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007768 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07007769 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007770 ALOGD("%s: returning existing instance of adev", __func__);
7771 ALOGD("%s: exit", __func__);
7772 pthread_mutex_unlock(&adev_init_lock);
7773 return 0;
7774 }
7775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007776 adev = calloc(1, sizeof(struct audio_device));
7777
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007778 if (!adev) {
7779 pthread_mutex_unlock(&adev_init_lock);
7780 return -ENOMEM;
7781 }
7782
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007783 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
7784
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05307785#ifdef DYNAMIC_LOG_ENABLED
7786 register_for_dynamic_logging("hal");
7787#endif
7788
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007789 adev->device.common.tag = HARDWARE_DEVICE_TAG;
7790 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7791 adev->device.common.module = (struct hw_module_t *)module;
7792 adev->device.common.close = adev_close;
7793
7794 adev->device.init_check = adev_init_check;
7795 adev->device.set_voice_volume = adev_set_voice_volume;
7796 adev->device.set_master_volume = adev_set_master_volume;
7797 adev->device.get_master_volume = adev_get_master_volume;
7798 adev->device.set_master_mute = adev_set_master_mute;
7799 adev->device.get_master_mute = adev_get_master_mute;
7800 adev->device.set_mode = adev_set_mode;
7801 adev->device.set_mic_mute = adev_set_mic_mute;
7802 adev->device.get_mic_mute = adev_get_mic_mute;
7803 adev->device.set_parameters = adev_set_parameters;
7804 adev->device.get_parameters = adev_get_parameters;
7805 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
7806 adev->device.open_output_stream = adev_open_output_stream;
7807 adev->device.close_output_stream = adev_close_output_stream;
7808 adev->device.open_input_stream = adev_open_input_stream;
7809 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307810 adev->device.create_audio_patch = adev_create_audio_patch;
7811 adev->device.release_audio_patch = adev_release_audio_patch;
7812 adev->device.get_audio_port = adev_get_audio_port;
7813 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007814 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307815 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007816
7817 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007818 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08007819 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007820 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007821 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007822 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08007823 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07007824 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307825 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07007826 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07007827 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007828 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08007829 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08007830 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007831 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05307832 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307833 adev->perf_lock_opts[0] = 0x101;
7834 adev->perf_lock_opts[1] = 0x20E;
7835 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007836 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307837
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007838 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07007839 adev->platform = platform_init(adev);
7840 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007841 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007842 free(adev->snd_dev_ref_cnt);
7843 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007844 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07007845 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7846 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08007847 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007848 return -EINVAL;
7849 }
Eric Laurentc4aef752013-09-12 17:45:53 -07007850
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307851 if (audio_extn_qaf_is_enabled()) {
7852 ret = audio_extn_qaf_init(adev);
7853 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007854 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307855 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007856 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307857 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7858 *device = NULL;
7859 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307860 return ret;
7861 }
7862
7863 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
7864 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
7865 }
7866
Derek Chend2530072014-11-24 12:39:14 -08007867 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
7868
Eric Laurentc4aef752013-09-12 17:45:53 -07007869 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
7870 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
7871 if (adev->visualizer_lib == NULL) {
7872 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
7873 } else {
7874 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
7875 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007876 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007877 "visualizer_hal_start_output");
7878 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007879 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007880 "visualizer_hal_stop_output");
7881 }
7882 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05307883 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08007884 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007885 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307886 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007887 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07007888
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007889 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
7890 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
7891 if (adev->offload_effects_lib == NULL) {
7892 ALOGE("%s: DLOPEN failed for %s", __func__,
7893 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7894 } else {
7895 ALOGV("%s: DLOPEN successful for %s", __func__,
7896 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7897 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05307898 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007899 "offload_effects_bundle_hal_start_output");
7900 adev->offload_effects_stop_output =
7901 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
7902 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007903 adev->offload_effects_set_hpx_state =
7904 (int (*)(bool))dlsym(adev->offload_effects_lib,
7905 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05307906 adev->offload_effects_get_parameters =
7907 (void (*)(struct str_parms *, struct str_parms *))
7908 dlsym(adev->offload_effects_lib,
7909 "offload_effects_bundle_get_parameters");
7910 adev->offload_effects_set_parameters =
7911 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
7912 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007913 }
7914 }
7915
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007916 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
7917 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
7918 if (adev->adm_lib == NULL) {
7919 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
7920 } else {
7921 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
7922 adev->adm_init = (adm_init_t)
7923 dlsym(adev->adm_lib, "adm_init");
7924 adev->adm_deinit = (adm_deinit_t)
7925 dlsym(adev->adm_lib, "adm_deinit");
7926 adev->adm_register_input_stream = (adm_register_input_stream_t)
7927 dlsym(adev->adm_lib, "adm_register_input_stream");
7928 adev->adm_register_output_stream = (adm_register_output_stream_t)
7929 dlsym(adev->adm_lib, "adm_register_output_stream");
7930 adev->adm_deregister_stream = (adm_deregister_stream_t)
7931 dlsym(adev->adm_lib, "adm_deregister_stream");
7932 adev->adm_request_focus = (adm_request_focus_t)
7933 dlsym(adev->adm_lib, "adm_request_focus");
7934 adev->adm_abandon_focus = (adm_abandon_focus_t)
7935 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007936 adev->adm_set_config = (adm_set_config_t)
7937 dlsym(adev->adm_lib, "adm_set_config");
7938 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
7939 dlsym(adev->adm_lib, "adm_request_focus_v2");
7940 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
7941 dlsym(adev->adm_lib, "adm_is_noirq_avail");
7942 adev->adm_on_routing_change = (adm_on_routing_change_t)
7943 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007944 }
7945 }
7946
Mingming Yin514a8bc2014-07-29 15:22:21 -07007947 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007948 //initialize this to false for now,
7949 //this will be set to true through set param
7950 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07007951
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07007952 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007953 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007954 adev->dsp_bit_width_enforce_mode =
7955 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007956
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307957 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
7958 &adev->streams_output_cfg_list,
7959 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007960
Kiran Kandi910e1862013-10-29 13:29:42 -07007961 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007962
7963 char value[PROPERTY_VALUE_MAX];
7964 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007965 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007966 trial = atoi(value);
7967 if (period_size_is_plausible_for_low_latency(trial)) {
7968 pcm_config_low_latency.period_size = trial;
7969 pcm_config_low_latency.start_threshold = trial / 4;
7970 pcm_config_low_latency.avail_min = trial / 4;
7971 configured_low_latency_capture_period_size = trial;
7972 }
7973 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007974 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007975 trial = atoi(value);
7976 if (period_size_is_plausible_for_low_latency(trial)) {
7977 configured_low_latency_capture_period_size = trial;
7978 }
7979 }
7980
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08007981 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
7982
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007983 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007984 af_period_multiplier = atoi(value);
7985 if (af_period_multiplier < 0)
7986 af_period_multiplier = 2;
7987 else if (af_period_multiplier > 4)
7988 af_period_multiplier = 4;
7989
7990 ALOGV("new period_multiplier = %d", af_period_multiplier);
7991 }
7992
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007993 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007994 pthread_mutex_unlock(&adev_init_lock);
7995
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007996 if (adev->adm_init)
7997 adev->adm_data = adev->adm_init();
7998
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307999 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308000 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008001 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308002
8003 audio_extn_snd_mon_init();
8004 pthread_mutex_lock(&adev->lock);
8005 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
8006 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07008007 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
8008 /*
8009 * if the battery state callback happens before charging can be queried,
8010 * it will be guarded with the adev->lock held in the cb function and so
8011 * the callback value will reflect the latest state
8012 */
8013 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308014 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08008015 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
8016 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308017 /* Allocate memory for Device config params */
8018 adev->device_cfg_params = (struct audio_device_config_param*)
8019 calloc(platform_get_max_codec_backend(),
8020 sizeof(struct audio_device_config_param));
8021 if (adev->device_cfg_params == NULL)
8022 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308023
Eric Laurent994a6932013-07-17 11:51:42 -07008024 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008025 return 0;
8026}
8027
8028static struct hw_module_methods_t hal_module_methods = {
8029 .open = adev_open,
8030};
8031
8032struct audio_module HAL_MODULE_INFO_SYM = {
8033 .common = {
8034 .tag = HARDWARE_MODULE_TAG,
8035 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
8036 .hal_api_version = HARDWARE_HAL_API_VERSION,
8037 .id = AUDIO_HARDWARE_MODULE_ID,
8038 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08008039 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008040 .methods = &hal_module_methods,
8041 },
8042};