blob: 99c291caa4e313a0219b2b61f7fa560b1b560b5b [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
Arun Mirpuriebe78a72018-10-04 18:23:46 -070092#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070093#define VOIP_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 */
341 [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700342
343 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
344 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530345 /* For Interactive Audio Streams */
346 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
347 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
348 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
349 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
350 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
351 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
352 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
353 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700354
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800355 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
356
357 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback"
Eric Laurentb23d5282013-05-14 15:27:20 -0700358};
359
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700360static const audio_usecase_t offload_usecases[] = {
361 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700362 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
363 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
364 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
365 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
366 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
367 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
368 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
369 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700370};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800371
Varun Balaraje49253e2017-07-06 19:48:56 +0530372static const audio_usecase_t interactive_usecases[] = {
373 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
374 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
375 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
376 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
377 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
378 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
379 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
380 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
381};
382
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800383#define STRING_TO_ENUM(string) { #string, string }
384
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800385struct string_to_enum {
386 const char *name;
387 uint32_t value;
388};
389
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700390static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800391 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800392 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
393 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
394 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700395 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800396 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
397 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800398 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700399 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
400 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
401 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
402 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
403 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
404 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
405 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
406 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
407 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
408 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
409 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800410};
411
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700412static const struct string_to_enum formats_name_to_enum_table[] = {
413 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
414 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
415 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700416 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
417 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
418 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700419 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800420 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
421 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700422 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800423};
424
425//list of all supported sample rates by HDMI specification.
426static const int out_hdmi_sample_rates[] = {
427 32000, 44100, 48000, 88200, 96000, 176400, 192000,
428};
429
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700430static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800431 STRING_TO_ENUM(32000),
432 STRING_TO_ENUM(44100),
433 STRING_TO_ENUM(48000),
434 STRING_TO_ENUM(88200),
435 STRING_TO_ENUM(96000),
436 STRING_TO_ENUM(176400),
437 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700438};
439
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700440static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700441static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700442static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700443//cache last MBDRC cal step level
444static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700445
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530446static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
447static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuriebe78a72018-10-04 18:23:46 -0700448static int out_set_mmap_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);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530450
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700451static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
452 int flags __unused)
453{
454 int dir = 0;
455 switch (uc_id) {
456 case USECASE_AUDIO_RECORD_LOW_LATENCY:
457 dir = 1;
458 case USECASE_AUDIO_PLAYBACK_ULL:
459 break;
460 default:
461 return false;
462 }
463
464 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
465 PCM_PLAYBACK : PCM_CAPTURE);
466 if (adev->adm_is_noirq_avail)
467 return adev->adm_is_noirq_avail(adev->adm_data,
468 adev->snd_card, dev_id, dir);
469 return false;
470}
471
472static void register_out_stream(struct stream_out *out)
473{
474 struct audio_device *adev = out->dev;
475 if (is_offload_usecase(out->usecase) ||
476 !adev->adm_register_output_stream)
477 return;
478
479 // register stream first for backward compatibility
480 adev->adm_register_output_stream(adev->adm_data,
481 out->handle,
482 out->flags);
483
484 if (!adev->adm_set_config)
485 return;
486
487 if (out->realtime)
488 adev->adm_set_config(adev->adm_data,
489 out->handle,
490 out->pcm, &out->config);
491}
492
493static void register_in_stream(struct stream_in *in)
494{
495 struct audio_device *adev = in->dev;
496 if (!adev->adm_register_input_stream)
497 return;
498
499 adev->adm_register_input_stream(adev->adm_data,
500 in->capture_handle,
501 in->flags);
502
503 if (!adev->adm_set_config)
504 return;
505
506 if (in->realtime)
507 adev->adm_set_config(adev->adm_data,
508 in->capture_handle,
509 in->pcm,
510 &in->config);
511}
512
513static void request_out_focus(struct stream_out *out, long ns)
514{
515 struct audio_device *adev = out->dev;
516
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700517 if (adev->adm_request_focus_v2)
518 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
519 else if (adev->adm_request_focus)
520 adev->adm_request_focus(adev->adm_data, out->handle);
521}
522
523static void request_in_focus(struct stream_in *in, long ns)
524{
525 struct audio_device *adev = in->dev;
526
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700527 if (adev->adm_request_focus_v2)
528 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
529 else if (adev->adm_request_focus)
530 adev->adm_request_focus(adev->adm_data, in->capture_handle);
531}
532
533static void release_out_focus(struct stream_out *out)
534{
535 struct audio_device *adev = out->dev;
536
537 if (adev->adm_abandon_focus)
538 adev->adm_abandon_focus(adev->adm_data, out->handle);
539}
540
541static void release_in_focus(struct stream_in *in)
542{
543 struct audio_device *adev = in->dev;
544 if (adev->adm_abandon_focus)
545 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
546}
547
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530548static int parse_snd_card_status(struct str_parms *parms, int *card,
549 card_status_t *status)
550{
551 char value[32]={0};
552 char state[32]={0};
553
554 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
555 if (ret < 0)
556 return -1;
557
558 // sscanf should be okay as value is of max length 32.
559 // same as sizeof state.
560 if (sscanf(value, "%d,%s", card, state) < 2)
561 return -1;
562
563 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
564 CARD_STATUS_OFFLINE;
565 return 0;
566}
567
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700568static inline void adjust_frames_for_device_delay(struct stream_out *out,
569 uint32_t *dsp_frames) {
570 // Adjustment accounts for A2dp encoder latency with offload usecases
571 // Note: Encoder latency is returned in ms.
572 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
573 unsigned long offset =
574 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
575 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
576 }
577}
578
vivek mehtaa76401a2015-04-24 14:12:15 -0700579__attribute__ ((visibility ("default")))
580bool audio_hw_send_gain_dep_calibration(int level) {
581 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700582 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700583
584 pthread_mutex_lock(&adev_init_lock);
585
586 if (adev != NULL && adev->platform != NULL) {
587 pthread_mutex_lock(&adev->lock);
588 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700589
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530590 // cache level info for any of the use case which
591 // was not started.
592 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700593
vivek mehtaa76401a2015-04-24 14:12:15 -0700594 pthread_mutex_unlock(&adev->lock);
595 } else {
596 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
597 }
598
599 pthread_mutex_unlock(&adev_init_lock);
600
601 return ret_val;
602}
603
Ashish Jain5106d362016-05-11 19:23:33 +0530604static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
605{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800606 bool gapless_enabled = false;
607 const char *mixer_ctl_name = "Compress Gapless Playback";
608 struct mixer_ctl *ctl;
609
610 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700611 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530612
613 /*Disable gapless if its AV playback*/
614 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800615
616 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
617 if (!ctl) {
618 ALOGE("%s: Could not get ctl for mixer cmd - %s",
619 __func__, mixer_ctl_name);
620 return -EINVAL;
621 }
622
623 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
624 ALOGE("%s: Could not set gapless mode %d",
625 __func__, gapless_enabled);
626 return -EINVAL;
627 }
628 return 0;
629}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700630
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700631__attribute__ ((visibility ("default")))
632int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
633 int table_size) {
634 int ret_val = 0;
635 ALOGV("%s: enter ... ", __func__);
636
637 pthread_mutex_lock(&adev_init_lock);
638 if (adev == NULL) {
639 ALOGW("%s: adev is NULL .... ", __func__);
640 goto done;
641 }
642
643 pthread_mutex_lock(&adev->lock);
644 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
645 pthread_mutex_unlock(&adev->lock);
646done:
647 pthread_mutex_unlock(&adev_init_lock);
648 ALOGV("%s: exit ... ", __func__);
649 return ret_val;
650}
651
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700652static bool is_supported_format(audio_format_t format)
653{
Eric Laurent86e17132013-09-12 17:49:30 -0700654 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530655 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530656 format == AUDIO_FORMAT_AAC_LC ||
657 format == AUDIO_FORMAT_AAC_HE_V1 ||
658 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530659 format == AUDIO_FORMAT_AAC_ADTS_LC ||
660 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
661 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530662 format == AUDIO_FORMAT_AAC_LATM_LC ||
663 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
664 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530665 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
666 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530667 format == AUDIO_FORMAT_PCM_FLOAT ||
668 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700669 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530670 format == AUDIO_FORMAT_AC3 ||
671 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700672 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530673 format == AUDIO_FORMAT_DTS ||
674 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800675 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530676 format == AUDIO_FORMAT_ALAC ||
677 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530678 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530679 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800680 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530681 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700682 format == AUDIO_FORMAT_APTX ||
683 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800684 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700685
686 return false;
687}
688
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700689static inline bool is_mmap_usecase(audio_usecase_t uc_id)
690{
691 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
692 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
693}
694
Avinash Vaish71a8b972014-07-24 15:36:33 +0530695static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
696 struct audio_usecase *uc_info)
697{
698 struct listnode *node;
699 struct audio_usecase *usecase;
700
701 if (uc_info == NULL)
702 return -EINVAL;
703
704 /* Re-route all voice usecases on the shared backend other than the
705 specified usecase to new snd devices */
706 list_for_each(node, &adev->usecase_list) {
707 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800708 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530709 enable_audio_route(adev, usecase);
710 }
711 return 0;
712}
713
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530714static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530715{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530716 ALOGV("%s", __func__);
717 audio_route_apply_and_update_path(adev->audio_route,
718 "asrc-mode");
719 adev->asrc_mode_enabled = true;
720}
721
722static void disable_asrc_mode(struct audio_device *adev)
723{
724 ALOGV("%s", __func__);
725 audio_route_reset_and_update_path(adev->audio_route,
726 "asrc-mode");
727 adev->asrc_mode_enabled = false;
728}
729
730/*
731 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
732 * 44.1 or Native DSD backends are enabled for any of current use case.
733 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
734 * - Disable current mix path use case(Headphone backend) and re-enable it with
735 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
736 * e.g. Naitve DSD or Headphone 44.1 -> + 48
737 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530738static void check_and_set_asrc_mode(struct audio_device *adev,
739 struct audio_usecase *uc_info,
740 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530741{
742 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530743 int i, num_new_devices = 0;
744 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
745 /*
746 *Split snd device for new combo use case
747 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
748 */
749 if (platform_split_snd_device(adev->platform,
750 snd_device,
751 &num_new_devices,
752 split_new_snd_devices) == 0) {
753 for (i = 0; i < num_new_devices; i++)
754 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
755 } else {
756 int new_backend_idx = platform_get_backend_index(snd_device);
757 if (((new_backend_idx == HEADPHONE_BACKEND) ||
758 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
759 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
760 !adev->asrc_mode_enabled) {
761 struct listnode *node = NULL;
762 struct audio_usecase *uc = NULL;
763 struct stream_out *curr_out = NULL;
764 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
765 int i, num_devices, ret = 0;
766 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530767
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530768 list_for_each(node, &adev->usecase_list) {
769 uc = node_to_item(node, struct audio_usecase, list);
770 curr_out = (struct stream_out*) uc->stream.out;
771 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
772 /*
773 *Split snd device for existing combo use case
774 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
775 */
776 ret = platform_split_snd_device(adev->platform,
777 uc->out_snd_device,
778 &num_devices,
779 split_snd_devices);
780 if (ret < 0 || num_devices == 0) {
781 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
782 split_snd_devices[0] = uc->out_snd_device;
783 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800784 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530785 for (i = 0; i < num_devices; i++) {
786 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
787 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
788 if((new_backend_idx == HEADPHONE_BACKEND) &&
789 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
790 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
791 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
792 __func__);
793 enable_asrc_mode(adev);
794 break;
795 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
796 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
797 (usecase_backend_idx == HEADPHONE_BACKEND)) {
798 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
799 __func__);
800 disable_audio_route(adev, uc);
801 disable_snd_device(adev, uc->out_snd_device);
802 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
803 if (new_backend_idx == DSD_NATIVE_BACKEND)
804 audio_route_apply_and_update_path(adev->audio_route,
805 "hph-true-highquality-mode");
806 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
807 (curr_out->bit_width >= 24))
808 audio_route_apply_and_update_path(adev->audio_route,
809 "hph-highquality-mode");
810 enable_asrc_mode(adev);
811 enable_snd_device(adev, uc->out_snd_device);
812 enable_audio_route(adev, uc);
813 break;
814 }
815 }
816 // reset split devices count
817 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800818 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530819 if (adev->asrc_mode_enabled)
820 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530821 }
822 }
823 }
824}
825
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700826#ifdef DYNAMIC_ECNS_ENABLED
827static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
828 struct audio_effect_config effect_config,
829 unsigned int param_value)
830{
831 char mixer_ctl_name[] = "Audio Effect";
832 struct mixer_ctl *ctl;
833 long set_values[6];
834 struct stream_in *in = adev->active_input;
835
836 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
837 if (!ctl) {
838 ALOGE("%s: Could not get mixer ctl - %s",
839 __func__, mixer_ctl_name);
840 return -EINVAL;
841 }
842
843 set_values[0] = 1; //0:Rx 1:Tx
844 set_values[1] = in->app_type_cfg.app_type;
845 set_values[2] = (long)effect_config.module_id;
846 set_values[3] = (long)effect_config.instance_id;
847 set_values[4] = (long)effect_config.param_id;
848 set_values[5] = param_value;
849
850 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
851
852 return 0;
853
854}
855
856static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
857 int effect_type, unsigned int *param_value)
858{
859 int ret = 0;
860 struct audio_effect_config other_effect_config;
861 struct audio_usecase *usecase = NULL;
862 struct stream_in *in = adev->active_input;
863
864 usecase = get_usecase_from_list(adev, in->usecase);
865 if (!usecase)
866 return -EINVAL;
867
868 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
869 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
870 if (ret < 0) {
871 ALOGE("%s Failed to get effect params %d", __func__, ret);
872 return ret;
873 }
874
875 if (module_id == other_effect_config.module_id) {
876 //Same module id for AEC/NS. Values need to be combined
877 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
878 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
879 *param_value |= other_effect_config.param_value;
880 }
881 }
882
883 return ret;
884}
885
886static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
887{
888 struct audio_effect_config effect_config;
889 struct audio_usecase *usecase = NULL;
890 int ret = 0;
891 unsigned int param_value = 0;
892 struct stream_in *in = adev->active_input;
893
894 if (!in) {
895 ALOGE("%s: Invalid input stream", __func__);
896 return -EINVAL;
897 }
898
899 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
900
901 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800902 if (usecase == NULL) {
903 ALOGE("%s: Could not find the usecase (%d) in the list",
904 __func__, in->usecase);
905 return -EINVAL;
906 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700907
908 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
909 if (ret < 0) {
910 ALOGE("%s Failed to get module id %d", __func__, ret);
911 return ret;
912 }
913 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
914 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
915
916 if(enable)
917 param_value = effect_config.param_value;
918
919 /*Special handling for AEC & NS effects Param values need to be
920 updated if module ids are same*/
921
922 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
923 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
924 if (ret < 0)
925 return ret;
926 }
927
928 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
929
930 return ret;
931}
932
933static void check_and_enable_effect(struct audio_device *adev)
934{
935
936 if (adev->active_input->enable_aec) {
937 enable_disable_effect(adev, EFFECT_AEC, true);
938 }
939
940 if (adev->active_input->enable_ns &&
941 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
942 enable_disable_effect(adev, EFFECT_NS, true);
943 }
944}
945#else
946#define enable_disable_effect(x, y, z) ENOSYS
947#define check_and_enable_effect(x) ENOSYS
948#endif
949
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700950int pcm_ioctl(struct pcm *pcm, int request, ...)
951{
952 va_list ap;
953 void * arg;
954 int pcm_fd = *(int*)pcm;
955
956 va_start(ap, request);
957 arg = va_arg(ap, void *);
958 va_end(ap);
959
960 return ioctl(pcm_fd, request, arg);
961}
962
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700963int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700964 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800965{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700966 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700967 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530968 struct stream_out *out = NULL;
Soumya Managolie7651c42018-06-28 16:04:57 +0530969 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800970
971 if (usecase == NULL)
972 return -EINVAL;
973
974 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
975
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800976 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700977 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800978 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800980
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800981#ifdef DS1_DOLBY_DAP_ENABLED
982 audio_extn_dolby_set_dmid(adev);
983 audio_extn_dolby_set_endpoint(adev);
984#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700985 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700986 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530987 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700988 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530989 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530990 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
991 out = usecase->stream.out;
992 if (out && out->compr)
993 audio_extn_utils_compress_set_clk_rec_mode(usecase);
994 }
995
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800996 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700997 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700998 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managolie7651c42018-06-28 16:04:57 +0530999 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1000 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1001 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1002 if (parms) {
1003 audio_extn_fm_set_parameters(adev, parms);
1004 str_parms_destroy(parms);
1005 }
1006 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001007 ALOGV("%s: exit", __func__);
1008 return 0;
1009}
1010
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001011int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001012 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001013{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001014 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001015 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001016
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301017 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001018 return -EINVAL;
1019
1020 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001021 if (usecase->type == PCM_CAPTURE)
1022 snd_device = usecase->in_snd_device;
1023 else
1024 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001025 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001026 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001027 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001028 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001029 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301030 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031 ALOGV("%s: exit", __func__);
1032 return 0;
1033}
1034
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001035int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001036 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001037{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301038 int i, num_devices = 0;
1039 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001040 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1041
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001042 if (snd_device < SND_DEVICE_MIN ||
1043 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001044 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001045 return -EINVAL;
1046 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001047
1048 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001049
1050 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
1051 ALOGE("%s: Invalid sound device returned", __func__);
1052 return -EINVAL;
1053 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001054 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -07001055 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001056 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001057 return 0;
1058 }
1059
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301060
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001061 if (audio_extn_spkr_prot_is_enabled())
1062 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001063
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001064 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1065 audio_extn_spkr_prot_is_enabled()) {
1066 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001067 adev->snd_dev_ref_cnt[snd_device]--;
1068 return -EINVAL;
1069 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001070 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001071 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001072 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001073 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001074 return -EINVAL;
1075 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001076 } else if (platform_split_snd_device(adev->platform,
1077 snd_device,
1078 &num_devices,
1079 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301080 for (i = 0; i < num_devices; i++) {
1081 enable_snd_device(adev, new_snd_devices[i]);
1082 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001083 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001084 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301085
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301086
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301087 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1088 (audio_extn_a2dp_start_playback() < 0)) {
1089 ALOGE(" fail to configure A2dp control path ");
1090 return -EINVAL;
1091 }
1092
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001093 /* due to the possibility of calibration overwrite between listen
1094 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001095 audio_extn_sound_trigger_update_device_status(snd_device,
1096 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301097 audio_extn_listen_update_device_status(snd_device,
1098 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001099 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001100 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001101 audio_extn_sound_trigger_update_device_status(snd_device,
1102 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301103 audio_extn_listen_update_device_status(snd_device,
1104 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001105 return -EINVAL;
1106 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001107 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001108 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301109
1110 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1111 !adev->native_playback_enabled &&
1112 audio_is_true_native_stream_active(adev)) {
1113 ALOGD("%s: %d: napb: enabling native mode in hardware",
1114 __func__, __LINE__);
1115 audio_route_apply_and_update_path(adev->audio_route,
1116 "true-native-mode");
1117 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301118 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001119 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1120 (audio_extn_ffv_get_stream() == adev->active_input)) {
1121 ALOGD("%s: init ec ref loopback", __func__);
1122 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1123 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001124 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001125 return 0;
1126}
1127
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001128int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001129 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001130{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301131 int i, num_devices = 0;
1132 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001133 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1134
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001135 if (snd_device < SND_DEVICE_MIN ||
1136 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001137 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001138 return -EINVAL;
1139 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001140 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1141 ALOGE("%s: device ref cnt is already 0", __func__);
1142 return -EINVAL;
1143 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001144
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001145 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001146
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001147 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1148 ALOGE("%s: Invalid sound device returned", __func__);
1149 return -EINVAL;
1150 }
1151
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001153 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301154
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001155 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1156 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001157 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001158
1159 // when speaker device is disabled, reset swap.
1160 // will be renabled on usecase start
1161 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001162 } else if (platform_split_snd_device(adev->platform,
1163 snd_device,
1164 &num_devices,
1165 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301166 for (i = 0; i < num_devices; i++) {
1167 disable_snd_device(adev, new_snd_devices[i]);
1168 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001169 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001170 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001171 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001172
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301173 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1174 audio_extn_a2dp_stop_playback();
1175
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001176 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301177 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301178 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1179 adev->native_playback_enabled) {
1180 ALOGD("%s: %d: napb: disabling native mode in hardware",
1181 __func__, __LINE__);
1182 audio_route_reset_and_update_path(adev->audio_route,
1183 "true-native-mode");
1184 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301185 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1186 adev->asrc_mode_enabled) {
1187 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301188 disable_asrc_mode(adev);
1189 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301190 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001191 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1192 (audio_extn_ffv_get_stream() == adev->active_input)) {
1193 ALOGD("%s: deinit ec ref loopback", __func__);
1194 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1195 }
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001196 audio_extn_utils_release_snd_device(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001197 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001199 return 0;
1200}
1201
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001202/*
1203 legend:
1204 uc - existing usecase
1205 new_uc - new usecase
1206 d1, d11, d2 - SND_DEVICE enums
1207 a1, a2 - corresponding ANDROID device enums
1208 B1, B2 - backend strings
1209
1210case 1
1211 uc->dev d1 (a1) B1
1212 new_uc->dev d1 (a1), d2 (a2) B1, B2
1213
1214 resolution: disable and enable uc->dev on d1
1215
1216case 2
1217 uc->dev d1 (a1) B1
1218 new_uc->dev d11 (a1) B1
1219
1220 resolution: need to switch uc since d1 and d11 are related
1221 (e.g. speaker and voice-speaker)
1222 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1223
1224case 3
1225 uc->dev d1 (a1) B1
1226 new_uc->dev d2 (a2) B2
1227
1228 resolution: no need to switch uc
1229
1230case 4
1231 uc->dev d1 (a1) B1
1232 new_uc->dev d2 (a2) B1
1233
1234 resolution: disable enable uc-dev on d2 since backends match
1235 we cannot enable two streams on two different devices if they
1236 share the same backend. e.g. if offload is on speaker device using
1237 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1238 using the same backend, offload must also be switched to voice-handset.
1239
1240case 5
1241 uc->dev d1 (a1) B1
1242 new_uc->dev d1 (a1), d2 (a2) B1
1243
1244 resolution: disable enable uc-dev on d2 since backends match
1245 we cannot enable two streams on two different devices if they
1246 share the same backend.
1247
1248case 6
1249 uc->dev d1 (a1) B1
1250 new_uc->dev d2 (a1) B2
1251
1252 resolution: no need to switch
1253
1254case 7
1255 uc->dev d1 (a1), d2 (a2) B1, B2
1256 new_uc->dev d1 (a1) B1
1257
1258 resolution: no need to switch
1259
Zhou Song4ba65882018-07-09 14:48:07 +08001260case 8
1261 uc->dev d1 (a1) B1
1262 new_uc->dev d11 (a1), d2 (a2) B1, B2
1263 resolution: compared to case 1, for this case, d1 and d11 are related
1264 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001265*/
1266static snd_device_t derive_playback_snd_device(void * platform,
1267 struct audio_usecase *uc,
1268 struct audio_usecase *new_uc,
1269 snd_device_t new_snd_device)
1270{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301271 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001272
1273 snd_device_t d1 = uc->out_snd_device;
1274 snd_device_t d2 = new_snd_device;
1275
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301276 switch (uc->type) {
1277 case TRANSCODE_LOOPBACK :
1278 a1 = uc->stream.inout->out_config.devices;
1279 a2 = new_uc->stream.inout->out_config.devices;
1280 break;
1281 default :
1282 a1 = uc->stream.out->devices;
1283 a2 = new_uc->stream.out->devices;
1284 break;
1285 }
1286
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001287 // Treat as a special case when a1 and a2 are not disjoint
1288 if ((a1 != a2) && (a1 & a2)) {
1289 snd_device_t d3[2];
1290 int num_devices = 0;
1291 int ret = platform_split_snd_device(platform,
1292 popcount(a1) > 1 ? d1 : d2,
1293 &num_devices,
1294 d3);
1295 if (ret < 0) {
1296 if (ret != -ENOSYS) {
1297 ALOGW("%s failed to split snd_device %d",
1298 __func__,
1299 popcount(a1) > 1 ? d1 : d2);
1300 }
1301 goto end;
1302 }
1303
1304 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1305 // But if it does happen, we need to give priority to d2 if
1306 // the combo devices active on the existing usecase share a backend.
1307 // This is because we cannot have a usecase active on a combo device
1308 // and a new usecase requests one device in this combo pair.
1309 if (platform_check_backends_match(d3[0], d3[1])) {
1310 return d2; // case 5
1311 } else {
Zhou Song671be042018-08-27 15:33:52 +08001312 // check if d1 is related to any of d3's OR
1313 // old uc is combo device but new_uc is one of the combo device
1314 if (d1 == d3[0] || d1 == d3[1] || popcount(a1) > 1)
1315 return d1; // case 1, 7
Zhou Song4ba65882018-07-09 14:48:07 +08001316 else
1317 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001318 }
1319 } else {
1320 if (platform_check_backends_match(d1, d2)) {
1321 return d2; // case 2, 4
1322 } else {
1323 return d1; // case 6, 3
1324 }
1325 }
1326
1327end:
1328 return d2; // return whatever was calculated before.
1329}
1330
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001331static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301332 struct audio_usecase *uc_info,
1333 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001334{
1335 struct listnode *node;
1336 struct audio_usecase *usecase;
1337 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301338 snd_device_t uc_derive_snd_device;
1339 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001340 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1341 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001342 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301343 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001344 /*
1345 * This function is to make sure that all the usecases that are active on
1346 * the hardware codec backend are always routed to any one device that is
1347 * handled by the hardware codec.
1348 * For example, if low-latency and deep-buffer usecases are currently active
1349 * on speaker and out_set_parameters(headset) is received on low-latency
1350 * output, then we have to make sure deep-buffer is also switched to headset,
1351 * because of the limitation that both the devices cannot be enabled
1352 * at the same time as they share the same backend.
1353 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001354 /*
1355 * This call is to check if we need to force routing for a particular stream
1356 * If there is a backend configuration change for the device when a
1357 * new stream starts, then ADM needs to be closed and re-opened with the new
1358 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001359 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001360 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001361 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1362 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301363 /* For a2dp device reconfigure all active sessions
1364 * with new AFE encoder format based on a2dp state
1365 */
1366 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1367 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1368 audio_extn_a2dp_is_force_device_switch()) {
1369 force_routing = true;
1370 force_restart_session = true;
1371 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301372 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1373
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001374 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001375 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001376 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001377 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1378 switch_device[i] = false;
1379
1380 list_for_each(node, &adev->usecase_list) {
1381 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001382
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301383 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1384 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301385 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301386 platform_get_snd_device_name(usecase->out_snd_device),
1387 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301388 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1389 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1390 usecase, uc_info, snd_device);
1391 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1392 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1393 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1394 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001395 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301396 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1397 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1398 ((force_restart_session) ||
1399 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301400 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1401 __func__, use_case_table[usecase->id],
1402 platform_get_snd_device_name(usecase->out_snd_device));
1403 disable_audio_route(adev, usecase);
1404 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301405 /* Enable existing usecase on derived playback device */
1406 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301407 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301408 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001409 }
1410 }
1411
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301412 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1413 num_uc_to_switch);
1414
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001415 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001416 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001417
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301418 /* Make sure the previous devices to be disabled first and then enable the
1419 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001420 list_for_each(node, &adev->usecase_list) {
1421 usecase = node_to_item(node, struct audio_usecase, list);
1422 if (switch_device[usecase->id]) {
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001423 /* Check if output sound device to be switched can be split and if any
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001424 of the split devices match with derived sound device */
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001425 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1426 &num_devices, split_snd_devices) == 0) {
1427 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1428 if (adev->snd_dev_ref_cnt[usecase->out_snd_device] == 0) {
1429 ALOGD("%s: disabling snd_device(%d)", __func__, usecase->out_snd_device);
1430 for (i = 0; i < num_devices; i++) {
1431 /* Disable devices that do not match with derived sound device */
1432 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1433 disable_snd_device(adev, split_snd_devices[i]);
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001434 }
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001435 audio_extn_utils_release_snd_device(usecase->out_snd_device);
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001436 }
1437 } else {
1438 disable_snd_device(adev, usecase->out_snd_device);
1439 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001440 }
1441 }
1442
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001443 list_for_each(node, &adev->usecase_list) {
1444 usecase = node_to_item(node, struct audio_usecase, list);
1445 if (switch_device[usecase->id]) {
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001446 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1447 &num_devices, split_snd_devices) == 0) {
1448 /* Enable derived sound device only if it does not match with
1449 one of the split sound devices. This is because the matching
1450 sound device was not disabled */
1451 bool should_enable = true;
1452 for (i = 0; i < num_devices; i++) {
1453 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1454 should_enable = false;
1455 break;
1456 }
1457 }
1458 if (should_enable)
1459 enable_snd_device(adev, derive_snd_device[usecase->id]);
1460 } else {
1461 enable_snd_device(adev, derive_snd_device[usecase->id]);
1462 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001463 }
1464 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001465
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001466 /* Re-route all the usecases on the shared backend other than the
1467 specified usecase to new snd devices */
1468 list_for_each(node, &adev->usecase_list) {
1469 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301470 /* Update the out_snd_device only before enabling the audio route */
1471 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301472 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301473 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301474 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301475 use_case_table[usecase->id],
1476 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001477 /* Update voc calibration before enabling VoIP route */
1478 if (usecase->type == VOIP_CALL)
1479 status = platform_switch_voice_call_device_post(adev->platform,
1480 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001481 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301482 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001483 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1484 out_set_voip_volume(&usecase->stream.out->stream,
1485 usecase->stream.out->volume_l,
1486 usecase->stream.out->volume_r);
1487 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301488 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001489 }
1490 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001491 }
1492}
1493
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301494static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001495 struct audio_usecase *uc_info,
1496 snd_device_t snd_device)
1497{
1498 struct listnode *node;
1499 struct audio_usecase *usecase;
1500 bool switch_device[AUDIO_USECASE_MAX];
1501 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301502 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001503 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001504
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301505 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1506 snd_device);
1507 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301508
1509 /*
1510 * Make sure out devices is checked against out codec backend device and
1511 * also in devices against in codec backend. Checking out device against in
1512 * codec backend or vice versa causes issues.
1513 */
1514 if (uc_info->type == PCM_CAPTURE)
1515 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001516 /*
1517 * This function is to make sure that all the active capture usecases
1518 * are always routed to the same input sound device.
1519 * For example, if audio-record and voice-call usecases are currently
1520 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1521 * is received for voice call then we have to make sure that audio-record
1522 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1523 * because of the limitation that two devices cannot be enabled
1524 * at the same time if they share the same backend.
1525 */
1526 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1527 switch_device[i] = false;
1528
1529 list_for_each(node, &adev->usecase_list) {
1530 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301531 /*
1532 * TODO: Enhance below condition to handle BT sco/USB multi recording
1533 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001534 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001535 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301536 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301537 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301538 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301539 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001540 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001541 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1542 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001543 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001544 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001545 switch_device[usecase->id] = true;
1546 num_uc_to_switch++;
1547 }
1548 }
1549
1550 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001551 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001552
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301553 /* Make sure the previous devices to be disabled first and then enable the
1554 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001555 list_for_each(node, &adev->usecase_list) {
1556 usecase = node_to_item(node, struct audio_usecase, list);
1557 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001558 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001559 }
1560 }
1561
1562 list_for_each(node, &adev->usecase_list) {
1563 usecase = node_to_item(node, struct audio_usecase, list);
1564 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001565 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001566 }
1567 }
1568
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001569 /* Re-route all the usecases on the shared backend other than the
1570 specified usecase to new snd devices */
1571 list_for_each(node, &adev->usecase_list) {
1572 usecase = node_to_item(node, struct audio_usecase, list);
1573 /* Update the in_snd_device only before enabling the audio route */
1574 if (switch_device[usecase->id] ) {
1575 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001576 if (usecase->type != VOICE_CALL) {
1577 /* Update voc calibration before enabling VoIP route */
1578 if (usecase->type == VOIP_CALL)
1579 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001580 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001581 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301582 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001583 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001584 }
1585 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001586 }
1587}
1588
Mingming Yin3a941d42016-02-17 18:08:05 -08001589static void reset_hdmi_sink_caps(struct stream_out *out) {
1590 int i = 0;
1591
1592 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1593 out->supported_channel_masks[i] = 0;
1594 }
1595 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1596 out->supported_formats[i] = 0;
1597 }
1598 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1599 out->supported_sample_rates[i] = 0;
1600 }
1601}
1602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001603/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001604static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001605{
Mingming Yin3a941d42016-02-17 18:08:05 -08001606 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001607 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001608
Mingming Yin3a941d42016-02-17 18:08:05 -08001609 reset_hdmi_sink_caps(out);
1610
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001611 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001612 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001613 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001614 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001615 }
1616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001617 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001618 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001619 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001620 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001621 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1622 case 6:
1623 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1624 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1625 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1626 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1627 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1628 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001629 break;
1630 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001631 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001632 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001633 break;
1634 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001635
1636 // check channel format caps
1637 i = 0;
1638 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1639 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1640 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1641 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1642 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1643 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1644 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1645 }
1646
Ben Romberger1aaaf862017-04-06 17:49:46 -07001647 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1648 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1649 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1650 }
1651
Mingming Yin3a941d42016-02-17 18:08:05 -08001652 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1653 ALOGV(":%s HDMI supports DTS format", __func__);
1654 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1655 }
1656
1657 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1658 ALOGV(":%s HDMI supports DTS HD format", __func__);
1659 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1660 }
1661
Naresh Tanniru928f0862017-04-07 16:44:23 -07001662 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1663 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1664 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1665 }
1666
Mingming Yin3a941d42016-02-17 18:08:05 -08001667
1668 // check sample rate caps
1669 i = 0;
1670 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1671 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1672 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1673 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1674 }
1675 }
1676
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001677 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678}
1679
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001680static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1681 uint32_t *supported_sample_rates __unused,
1682 uint32_t max_rates __unused)
1683{
1684 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1685 supported_sample_rates,
1686 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301687 ssize_t i = 0;
1688
1689 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001690 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1691 supported_sample_rates[i]);
1692 }
1693 return count;
1694}
1695
1696static inline int read_usb_sup_channel_masks(bool is_playback,
1697 audio_channel_mask_t *supported_channel_masks,
1698 uint32_t max_masks)
1699{
1700 int channels = audio_extn_usb_get_max_channels(is_playback);
1701 int channel_count;
1702 uint32_t num_masks = 0;
1703 if (channels > MAX_HIFI_CHANNEL_COUNT)
1704 channels = MAX_HIFI_CHANNEL_COUNT;
1705
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301706 channel_count = DEFAULT_CHANNEL_COUNT;
1707
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001708 if (is_playback) {
1709 // For playback we never report mono because the framework always outputs stereo
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001710 // audio_channel_out_mask_from_count() does return positional masks for channel counts
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301711 // above 2 but we want indexed masks here.
1712 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001713 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001714 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1715 // indexed mask
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301716 supported_channel_masks[num_masks++] = audio_channel_in_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001717 }
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301718
1719 for (channel_count = channels; ((channel_count >= DEFAULT_CHANNEL_COUNT) &&
1720 (num_masks < max_masks)); channel_count--) {
1721 supported_channel_masks[num_masks++] =
1722 audio_channel_mask_for_index_assignment_from_count(channel_count);
1723 }
1724
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001725 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1726 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1727 return num_masks;
1728}
1729
1730static inline int read_usb_sup_formats(bool is_playback __unused,
1731 audio_format_t *supported_formats,
1732 uint32_t max_formats __unused)
1733{
1734 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1735 switch (bitwidth) {
1736 case 24:
1737 // XXX : usb.c returns 24 for s24 and s24_le?
1738 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1739 break;
1740 case 32:
1741 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1742 break;
1743 case 16:
1744 default :
1745 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1746 break;
1747 }
1748 ALOGV("%s: %s supported format %d", __func__,
1749 is_playback ? "P" : "C", bitwidth);
1750 return 1;
1751}
1752
1753static inline int read_usb_sup_params_and_compare(bool is_playback,
1754 audio_format_t *format,
1755 audio_format_t *supported_formats,
1756 uint32_t max_formats,
1757 audio_channel_mask_t *mask,
1758 audio_channel_mask_t *supported_channel_masks,
1759 uint32_t max_masks,
1760 uint32_t *rate,
1761 uint32_t *supported_sample_rates,
1762 uint32_t max_rates) {
1763 int ret = 0;
1764 int num_formats;
1765 int num_masks;
1766 int num_rates;
1767 int i;
1768
1769 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1770 max_formats);
1771 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1772 max_masks);
1773
1774 num_rates = read_usb_sup_sample_rates(is_playback,
1775 supported_sample_rates, max_rates);
1776
1777#define LUT(table, len, what, dflt) \
1778 for (i=0; i<len && (table[i] != what); i++); \
1779 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1780
1781 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1782 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1783 LUT(supported_sample_rates, num_rates, *rate, 0);
1784
1785#undef LUT
1786 return ret < 0 ? -EINVAL : 0; // HACK TBD
1787}
1788
Alexy Josephb1379942016-01-29 15:49:38 -08001789audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001790 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001791{
1792 struct audio_usecase *usecase;
1793 struct listnode *node;
1794
1795 list_for_each(node, &adev->usecase_list) {
1796 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001797 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001798 ALOGV("%s: usecase id %d", __func__, usecase->id);
1799 return usecase->id;
1800 }
1801 }
1802 return USECASE_INVALID;
1803}
1804
Alexy Josephb1379942016-01-29 15:49:38 -08001805struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001806 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001807{
1808 struct audio_usecase *usecase;
1809 struct listnode *node;
1810
1811 list_for_each(node, &adev->usecase_list) {
1812 usecase = node_to_item(node, struct audio_usecase, list);
1813 if (usecase->id == uc_id)
1814 return usecase;
1815 }
1816 return NULL;
1817}
1818
Dhananjay Kumard4833242016-10-06 22:09:12 +05301819struct stream_in *get_next_active_input(const struct audio_device *adev)
1820{
1821 struct audio_usecase *usecase;
1822 struct listnode *node;
1823
1824 list_for_each_reverse(node, &adev->usecase_list) {
1825 usecase = node_to_item(node, struct audio_usecase, list);
1826 if (usecase->type == PCM_CAPTURE)
1827 return usecase->stream.in;
1828 }
1829 return NULL;
1830}
1831
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301832/*
1833 * is a true native playback active
1834 */
1835bool audio_is_true_native_stream_active(struct audio_device *adev)
1836{
1837 bool active = false;
1838 int i = 0;
1839 struct listnode *node;
1840
1841 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1842 ALOGV("%s:napb: not in true mode or non hdphones device",
1843 __func__);
1844 active = false;
1845 goto exit;
1846 }
1847
1848 list_for_each(node, &adev->usecase_list) {
1849 struct audio_usecase *uc;
1850 uc = node_to_item(node, struct audio_usecase, list);
1851 struct stream_out *curr_out =
1852 (struct stream_out*) uc->stream.out;
1853
1854 if (curr_out && PCM_PLAYBACK == uc->type) {
1855 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1856 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1857 uc->id, curr_out->sample_rate,
1858 curr_out->bit_width,
1859 platform_get_snd_device_name(uc->out_snd_device));
1860
1861 if (is_offload_usecase(uc->id) &&
1862 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1863 active = true;
1864 ALOGD("%s:napb:native stream detected", __func__);
1865 }
1866 }
1867 }
1868exit:
1869 return active;
1870}
1871
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001872uint32_t adev_get_dsp_bit_width_enforce_mode()
1873{
1874 if (adev == NULL) {
1875 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1876 return 0;
1877 }
1878 return adev->dsp_bit_width_enforce_mode;
1879}
1880
1881static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1882{
1883 char value[PROPERTY_VALUE_MAX];
1884 int trial;
1885 uint32_t dsp_bit_width_enforce_mode = 0;
1886
1887 if (!mixer) {
1888 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1889 __func__);
1890 return 0;
1891 }
1892
1893 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1894 value, NULL) > 0) {
1895 trial = atoi(value);
1896 switch (trial) {
1897 case 16:
1898 dsp_bit_width_enforce_mode = 16;
1899 break;
1900 case 24:
1901 dsp_bit_width_enforce_mode = 24;
1902 break;
1903 case 32:
1904 dsp_bit_width_enforce_mode = 32;
1905 break;
1906 default:
1907 dsp_bit_width_enforce_mode = 0;
1908 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1909 break;
1910 }
1911 }
1912
1913 return dsp_bit_width_enforce_mode;
1914}
1915
1916static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1917 uint32_t enforce_mode,
1918 bool enable)
1919{
1920 struct mixer_ctl *ctl = NULL;
1921 const char *mixer_ctl_name = "ASM Bit Width";
1922 uint32_t asm_bit_width_mode = 0;
1923
1924 if (enforce_mode == 0) {
1925 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1926 return;
1927 }
1928
1929 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1930 if (!ctl) {
1931 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1932 __func__, mixer_ctl_name);
1933 return;
1934 }
1935
1936 if (enable)
1937 asm_bit_width_mode = enforce_mode;
1938 else
1939 asm_bit_width_mode = 0;
1940
1941 ALOGV("%s DSP bit width feature status is %d width=%d",
1942 __func__, enable, asm_bit_width_mode);
1943 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1944 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1945 asm_bit_width_mode);
1946
1947 return;
1948}
1949
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301950/*
1951 * if native DSD playback active
1952 */
1953bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1954{
1955 bool active = false;
1956 struct listnode *node = NULL;
1957 struct audio_usecase *uc = NULL;
1958 struct stream_out *curr_out = NULL;
1959
1960 list_for_each(node, &adev->usecase_list) {
1961 uc = node_to_item(node, struct audio_usecase, list);
1962 curr_out = (struct stream_out*) uc->stream.out;
1963
1964 if (curr_out && PCM_PLAYBACK == uc->type &&
1965 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1966 active = true;
1967 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301968 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301969 }
1970 }
1971 return active;
1972}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301973
1974static bool force_device_switch(struct audio_usecase *usecase)
1975{
1976 bool ret = false;
1977 bool is_it_true_mode = false;
1978
Zhou Song30f2c3e2018-02-08 14:02:15 +08001979 if (usecase->type == PCM_CAPTURE ||
1980 usecase->type == TRANSCODE_LOOPBACK) {
1981 return false;
1982 }
1983
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001984 if(usecase->stream.out == NULL) {
1985 ALOGE("%s: stream.out is NULL", __func__);
1986 return false;
1987 }
1988
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301989 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001990 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1991 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1992 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301993 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1994 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1995 (!is_it_true_mode && adev->native_playback_enabled)){
1996 ret = true;
1997 ALOGD("napb: time to toggle native mode");
1998 }
1999 }
2000
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302001 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302002 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2003 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002004 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302005 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302006 ALOGD("Force a2dp device switch to update new encoder config");
2007 ret = true;
2008 }
2009
Manish Dewangan671a4202017-08-18 17:30:46 +05302010 if (usecase->stream.out->stream_config_changed) {
2011 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2012 return true;
2013 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302014 return ret;
2015}
2016
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302017bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2018{
2019 bool ret=false;
2020 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2021 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2022 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2023 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2024 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2025 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2026 ret = true;
2027
2028 return ret;
2029}
2030
2031bool is_a2dp_device(snd_device_t out_snd_device)
2032{
2033 bool ret=false;
2034 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2035 ret = true;
2036
2037 return ret;
2038}
2039
2040bool is_bt_soc_on(struct audio_device *adev)
2041{
2042 struct mixer_ctl *ctl;
2043 char *mixer_ctl_name = "BT SOC status";
2044 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2045 bool bt_soc_status = true;
2046 if (!ctl) {
2047 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2048 __func__, mixer_ctl_name);
2049 /*This is to ensure we dont break targets which dont have the kernel change*/
2050 return true;
2051 }
2052 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2053 ALOGD("BT SOC status: %d",bt_soc_status);
2054 return bt_soc_status;
2055}
2056
2057int out_standby_l(struct audio_stream *stream);
2058
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002059int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002061 snd_device_t out_snd_device = SND_DEVICE_NONE;
2062 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002063 struct audio_usecase *usecase = NULL;
2064 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002065 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002066 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302067 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002068 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002069 int status = 0;
Weiyin Jiang5d608082018-02-01 17:24:33 +08002070 audio_devices_t audio_device;
2071 audio_channel_mask_t channel_mask;
2072 int sample_rate;
2073 int acdb_id;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002074
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302075 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2076
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002077 usecase = get_usecase_from_list(adev, uc_id);
2078 if (usecase == NULL) {
2079 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2080 return -EINVAL;
2081 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002082
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002083 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002084 (usecase->type == VOIP_CALL) ||
2085 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302086 if(usecase->stream.out == NULL) {
2087 ALOGE("%s: stream.out is NULL", __func__);
2088 return -EINVAL;
2089 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002090 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002091 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002092 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002093 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302094 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
2095 if (usecase->stream.inout == NULL) {
2096 ALOGE("%s: stream.inout is NULL", __func__);
2097 return -EINVAL;
2098 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302099 stream_out.devices = usecase->stream.inout->out_config.devices;
2100 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2101 stream_out.format = usecase->stream.inout->out_config.format;
2102 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2103 out_snd_device = platform_get_output_snd_device(adev->platform,
2104 &stream_out);
2105 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302106 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002107 } else {
2108 /*
2109 * If the voice call is active, use the sound devices of voice call usecase
2110 * so that it would not result any device switch. All the usecases will
2111 * be switched to new device when select_devices() is called for voice call
2112 * usecase. This is to avoid switching devices for voice call when
2113 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002114 * choose voice call device only if the use case device is
2115 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002116 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002117 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002118 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002119 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002120 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2121 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302122 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2123 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002124 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002125 in_snd_device = vc_usecase->in_snd_device;
2126 out_snd_device = vc_usecase->out_snd_device;
2127 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002128 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002129 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002130 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002131 if ((voip_usecase != NULL) &&
2132 (usecase->type == PCM_PLAYBACK) &&
2133 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002134 out_snd_device_backend_match = platform_check_backends_match(
2135 voip_usecase->out_snd_device,
2136 platform_get_output_snd_device(
2137 adev->platform,
2138 usecase->stream.out));
2139 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002140 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002141 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2142 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002143 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002144 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002145 in_snd_device = voip_usecase->in_snd_device;
2146 out_snd_device = voip_usecase->out_snd_device;
2147 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002148 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002149 hfp_ucid = audio_extn_hfp_get_usecase();
2150 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002151 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002152 in_snd_device = hfp_usecase->in_snd_device;
2153 out_snd_device = hfp_usecase->out_snd_device;
2154 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002155 }
2156 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302157 if (usecase->stream.out == NULL) {
2158 ALOGE("%s: stream.out is NULL", __func__);
2159 return -EINVAL;
2160 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002161 usecase->devices = usecase->stream.out->devices;
2162 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002163 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002164 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002165 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002166 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleiz3ca773f2018-10-12 15:49:35 +08002167 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002168 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2169
2170 if ((usecase->stream.out != NULL &&
2171 voip_usecase != NULL &&
2172 usecase->stream.out->usecase == voip_usecase->id) &&
2173 adev->active_input &&
kunleiz3ca773f2018-10-12 15:49:35 +08002174 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002175 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002176 select_devices(adev, adev->active_input->usecase);
2177 }
2178 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002179 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302180 if (usecase->stream.in == NULL) {
2181 ALOGE("%s: stream.in is NULL", __func__);
2182 return -EINVAL;
2183 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002184 usecase->devices = usecase->stream.in->device;
2185 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002186 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002187 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002188 if (adev->active_input &&
2189 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302190 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002191 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2192 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2193 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2194 out_device = voip_usecase->stream.out->devices;
2195 else if (adev->primary_output && !adev->primary_output->standby)
2196 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002197 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002198 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2199 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002200 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002201 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002202 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002203 }
2204 }
2205
2206 if (out_snd_device == usecase->out_snd_device &&
2207 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302208
2209 if (!force_device_switch(usecase))
2210 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002211 }
2212
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302213 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
2214 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
2215 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2216 return 0;
2217 }
2218
sangwoobc677242013-08-08 16:53:43 +09002219 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07002220 out_snd_device, platform_get_snd_device_name(out_snd_device),
2221 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002222
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223 /*
2224 * Limitation: While in call, to do a device switch we need to disable
2225 * and enable both RX and TX devices though one of them is same as current
2226 * device.
2227 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002228 if ((usecase->type == VOICE_CALL) &&
2229 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2230 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002231 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002232 }
2233
2234 if (((usecase->type == VOICE_CALL) ||
2235 (usecase->type == VOIP_CALL)) &&
2236 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2237 /* Disable sidetone only if voice/voip call already exists */
2238 if (voice_is_call_state_active(adev) ||
2239 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002240 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002241
2242 /* Disable aanc only if voice call exists */
2243 if (voice_is_call_state_active(adev))
2244 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002245 }
2246
Zhou Songc66eb7e2017-08-08 18:29:07 +08002247 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302248 (!audio_extn_a2dp_is_ready())) {
2249 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002250 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302251 }
2252
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002253 /* Disable current sound devices */
2254 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002255 disable_audio_route(adev, usecase);
2256 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257 }
2258
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002259 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002260 disable_audio_route(adev, usecase);
2261 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002262 }
2263
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002264 /* Applicable only on the targets that has external modem.
2265 * New device information should be sent to modem before enabling
2266 * the devices to reduce in-call device switch time.
2267 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002268 if ((usecase->type == VOICE_CALL) &&
2269 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2270 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002271 status = platform_switch_voice_call_enable_device_config(adev->platform,
2272 out_snd_device,
2273 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002274 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002275
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002276 /* Enable new sound devices */
2277 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002278 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302279 if (platform_check_codec_asrc_support(adev->platform))
2280 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002281 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002282 }
2283
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002284 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302285 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002286 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002287 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002288
Avinash Vaish71a8b972014-07-24 15:36:33 +05302289 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002290 status = platform_switch_voice_call_device_post(adev->platform,
2291 out_snd_device,
2292 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302293 enable_audio_route_for_voice_usecases(adev, usecase);
2294 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002295
sangwoo170731f2013-06-08 15:36:36 +09002296 usecase->in_snd_device = in_snd_device;
2297 usecase->out_snd_device = out_snd_device;
2298
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302299 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2300 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302301 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002302 if ((24 == usecase->stream.out->bit_width) &&
2303 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2304 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2305 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2306 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2307 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2308 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2309 /*
2310 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2311 * configured device sample rate, if not update the COPP rate to be equal to the
2312 * device sample rate, else open COPP at stream sample rate
2313 */
2314 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2315 usecase->stream.out->sample_rate,
2316 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302317 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2318 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002319 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2320 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2321 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2322 }
2323
Weiyin Jiang5d608082018-02-01 17:24:33 +08002324 /* Cache stream information to be notified to gef clients */
2325 audio_device = usecase->stream.out->devices;
2326 channel_mask = usecase->stream.out->channel_mask;
2327 sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
2328 acdb_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302329 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002330 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002331
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002332 /* If input stream is already running then effect needs to be
2333 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002334 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2335 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002336 check_and_enable_effect(adev);
2337
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002338 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002339 /* Enable aanc only if voice call exists */
2340 if (voice_is_call_state_active(adev))
2341 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2342
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002343 /* Enable sidetone only if other voice/voip call already exists */
2344 if (voice_is_call_state_active(adev) ||
2345 voice_extn_compress_voip_is_started(adev))
2346 voice_set_sidetone(adev, out_snd_device, true);
2347 }
2348
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002349 /* Applicable only on the targets that has external modem.
2350 * Enable device command should be sent to modem only after
2351 * enabling voice call mixer controls
2352 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002353 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002354 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2355 out_snd_device,
2356 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302357
2358 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2359
2360 if (usecase->type == VOIP_CALL) {
2361 if (adev->active_input != NULL &&
2362 !adev->active_input->standby) {
2363 if (is_bt_soc_on(adev) == false){
2364 ALOGD("BT SCO MIC disconnected while in connection");
2365 if (adev->active_input->pcm != NULL)
2366 pcm_stop(adev->active_input->pcm);
2367 }
2368 }
2369 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2370 && usecase->stream.out->started) {
2371 if (is_bt_soc_on(adev) == false) {
2372 ALOGD("BT SCO/A2DP disconnected while in connection");
2373 out_standby_l(&usecase->stream.out->stream.common);
2374 }
2375 }
2376 } else if ((usecase->stream.out != NULL) &&
2377 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2378 usecase->stream.out->started) {
2379 if (is_bt_soc_on(adev) == false) {
2380 ALOGD("BT SCO/A2dp disconnected while in connection");
2381 out_standby_l(&usecase->stream.out->stream.common);
2382 }
2383 }
2384 }
2385
Weiyin Jiang5d608082018-02-01 17:24:33 +08002386 /* Notify device change info to effect clients registered
2387 * NOTE: device lock has to be unlock temporarily here.
2388 * To the worst case, we notify stale info to clients.
2389 */
2390 if (usecase->type == PCM_PLAYBACK) {
2391 pthread_mutex_unlock(&adev->lock);
2392 audio_extn_gef_notify_device_config(audio_device, channel_mask, sample_rate, acdb_id);
2393 pthread_mutex_lock(&adev->lock);
2394 }
2395
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302396 ALOGD("%s: done",__func__);
2397
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002398 return status;
2399}
2400
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002401static int stop_input_stream(struct stream_in *in)
2402{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302403 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002404 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302405
2406 if (in == NULL) {
2407 ALOGE("%s: stream_in ptr is NULL", __func__);
2408 return -EINVAL;
2409 }
2410
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002411 struct audio_device *adev = in->dev;
2412
Eric Laurent994a6932013-07-17 11:51:42 -07002413 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002414 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415 uc_info = get_usecase_from_list(adev, in->usecase);
2416 if (uc_info == NULL) {
2417 ALOGE("%s: Could not find the usecase (%d) in the list",
2418 __func__, in->usecase);
2419 return -EINVAL;
2420 }
2421
Derek Chencdd17c72014-11-24 12:39:14 -08002422 if (uc_info->in_snd_device != SND_DEVICE_NONE) {
2423 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2424 ALOGE("%s: failed to stop ext hw plugin", __func__);
2425 }
2426
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002427 /* Close in-call recording streams */
2428 voice_check_and_stop_incall_rec_usecase(adev, in);
2429
Eric Laurent150dbfe2013-02-27 14:31:02 -08002430 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002431 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002432
2433 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002434 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002436 list_remove(&uc_info->list);
2437 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002439 adev->active_input = get_next_active_input(adev);
2440
Eric Laurent994a6932013-07-17 11:51:42 -07002441 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002442 return ret;
2443}
2444
2445int start_input_stream(struct stream_in *in)
2446{
2447 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002448 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002449 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302450
2451 if (in == NULL) {
2452 ALOGE("%s: stream_in ptr is NULL", __func__);
2453 return -EINVAL;
2454 }
2455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002457 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002458 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002459
Mingming Yin2664a5b2015-09-03 10:53:11 -07002460 if (get_usecase_from_list(adev, usecase) == NULL)
2461 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302462 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2463 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002464
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302465 if (CARD_STATUS_OFFLINE == in->card_status||
2466 CARD_STATUS_OFFLINE == adev->card_status) {
2467 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302468 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302469 goto error_config;
2470 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302471
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302472 if (audio_is_bluetooth_sco_device(in->device)) {
2473 if (!adev->bt_sco_on) {
2474 ALOGE("%s: SCO profile is not ready, return error", __func__);
2475 ret = -EIO;
2476 goto error_config;
2477 }
2478 }
2479
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002480 /* Check if source matches incall recording usecase criteria */
2481 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2482 if (ret)
2483 goto error_config;
2484 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002485 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2486
2487 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2488 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2489 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002490 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002491 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002492
Eric Laurentb23d5282013-05-14 15:27:20 -07002493 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494 if (in->pcm_device_id < 0) {
2495 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2496 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002497 ret = -EINVAL;
2498 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002500
2501 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002503
2504 if (!uc_info) {
2505 ret = -ENOMEM;
2506 goto error_config;
2507 }
2508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509 uc_info->id = in->usecase;
2510 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002511 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002512 uc_info->devices = in->device;
2513 uc_info->in_snd_device = SND_DEVICE_NONE;
2514 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002516 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302517 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2518 adev->perf_lock_opts,
2519 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002520 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521
Derek Chencdd17c72014-11-24 12:39:14 -08002522 if (uc_info->in_snd_device != SND_DEVICE_NONE) {
2523 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2524 ALOGE("%s: failed to start ext hw plugin", __func__);
2525 }
2526
Haynes Mathew George16081042017-05-31 17:16:49 -07002527 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302528 ret = audio_extn_cin_start_input_stream(in);
2529 if (ret)
2530 goto error_open;
2531 else
2532 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002533 }
2534
Haynes Mathew George16081042017-05-31 17:16:49 -07002535 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002536 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002537 ALOGE("%s: pcm stream not ready", __func__);
2538 goto error_open;
2539 }
2540 ret = pcm_start(in->pcm);
2541 if (ret < 0) {
2542 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2543 goto error_open;
2544 }
2545 } else {
2546 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2547 unsigned int pcm_open_retry_count = 0;
2548
2549 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2550 flags |= PCM_MMAP | PCM_NOIRQ;
2551 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2552 } else if (in->realtime) {
2553 flags |= PCM_MMAP | PCM_NOIRQ;
2554 }
2555
Garmond Leunge2433c32017-09-28 21:51:22 -07002556 if (audio_extn_ffv_get_stream() == in) {
2557 ALOGD("%s: ffv stream, update pcm config", __func__);
2558 audio_extn_ffv_update_pcm_config(&config);
2559 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002560 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2561 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2562
2563 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002564 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002565 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002566 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002567 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05302568 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
2569 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2570 adev->card_status = CARD_STATUS_OFFLINE;
2571 in->card_status = CARD_STATUS_OFFLINE;
2572 ret = -EIO;
2573 goto error_open;
2574 }
2575
Haynes Mathew George16081042017-05-31 17:16:49 -07002576 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2577 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2578 if (in->pcm != NULL) {
2579 pcm_close(in->pcm);
2580 in->pcm = NULL;
2581 }
2582 if (pcm_open_retry_count-- == 0) {
2583 ret = -EIO;
2584 goto error_open;
2585 }
2586 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2587 continue;
2588 }
2589 break;
2590 }
2591
2592 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002593 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002594 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002595 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002596 if (ret < 0) {
2597 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2598 pcm_close(in->pcm);
2599 in->pcm = NULL;
2600 goto error_open;
2601 }
2602 register_in_stream(in);
2603 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002604 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002605 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002606 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002607 if (ret < 0) {
2608 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002609 pcm_close(in->pcm);
2610 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002611 goto error_open;
2612 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002613 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002614 }
2615
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002616 check_and_enable_effect(adev);
2617
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302618done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302619 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002620 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002621
Eric Laurentc8400632013-02-14 19:04:54 -08002622 return ret;
2623
2624error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302625 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002627error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302628 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302629 /*
2630 * sleep 50ms to allow sufficient time for kernel
2631 * drivers to recover incases like SSR.
2632 */
2633 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002634 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002635
2636 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002637}
2638
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002639void lock_input_stream(struct stream_in *in)
2640{
2641 pthread_mutex_lock(&in->pre_lock);
2642 pthread_mutex_lock(&in->lock);
2643 pthread_mutex_unlock(&in->pre_lock);
2644}
2645
2646void lock_output_stream(struct stream_out *out)
2647{
2648 pthread_mutex_lock(&out->pre_lock);
2649 pthread_mutex_lock(&out->lock);
2650 pthread_mutex_unlock(&out->pre_lock);
2651}
2652
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002653/* must be called with out->lock locked */
2654static int send_offload_cmd_l(struct stream_out* out, int command)
2655{
2656 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2657
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002658 if (!cmd) {
2659 ALOGE("failed to allocate mem for command 0x%x", command);
2660 return -ENOMEM;
2661 }
2662
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002663 ALOGVV("%s %d", __func__, command);
2664
2665 cmd->cmd = command;
2666 list_add_tail(&out->offload_cmd_list, &cmd->node);
2667 pthread_cond_signal(&out->offload_cond);
2668 return 0;
2669}
2670
2671/* must be called iwth out->lock locked */
2672static void stop_compressed_output_l(struct stream_out *out)
2673{
2674 out->offload_state = OFFLOAD_STATE_IDLE;
2675 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002676 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002677 if (out->compr != NULL) {
2678 compress_stop(out->compr);
2679 while (out->offload_thread_blocked) {
2680 pthread_cond_wait(&out->cond, &out->lock);
2681 }
2682 }
2683}
2684
Varun Balaraje49253e2017-07-06 19:48:56 +05302685bool is_interactive_usecase(audio_usecase_t uc_id)
2686{
2687 unsigned int i;
2688 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2689 if (uc_id == interactive_usecases[i])
2690 return true;
2691 }
2692 return false;
2693}
2694
2695static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2696{
2697 audio_usecase_t ret_uc = USECASE_INVALID;
2698 unsigned int intract_uc_index;
2699 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2700
2701 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2702 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2703 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2704 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2705 ret_uc = interactive_usecases[intract_uc_index];
2706 break;
2707 }
2708 }
2709
2710 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2711 return ret_uc;
2712}
2713
2714static void free_interactive_usecase(struct audio_device *adev,
2715 audio_usecase_t uc_id)
2716{
2717 unsigned int interact_uc_index;
2718 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2719
2720 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2721 if (interactive_usecases[interact_uc_index] == uc_id) {
2722 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2723 break;
2724 }
2725 }
2726 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2727}
2728
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002729bool is_offload_usecase(audio_usecase_t uc_id)
2730{
2731 unsigned int i;
2732 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2733 if (uc_id == offload_usecases[i])
2734 return true;
2735 }
2736 return false;
2737}
2738
Dhananjay Kumarac341582017-02-23 23:42:25 +05302739static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002740{
vivek mehta446c3962015-09-14 10:57:35 -07002741 audio_usecase_t ret_uc = USECASE_INVALID;
2742 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002743 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002744 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302745 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002746 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2747 else
2748 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002749
vivek mehta446c3962015-09-14 10:57:35 -07002750 pthread_mutex_lock(&adev->lock);
2751 if (get_usecase_from_list(adev, ret_uc) != NULL)
2752 ret_uc = USECASE_INVALID;
2753 pthread_mutex_unlock(&adev->lock);
2754
2755 return ret_uc;
2756 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002757
2758 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002759 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2760 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2761 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2762 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002763 break;
2764 }
2765 }
vivek mehta446c3962015-09-14 10:57:35 -07002766
2767 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2768 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002769}
2770
2771static void free_offload_usecase(struct audio_device *adev,
2772 audio_usecase_t uc_id)
2773{
vivek mehta446c3962015-09-14 10:57:35 -07002774 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002775 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002776
2777 if (!adev->multi_offload_enable)
2778 return;
2779
2780 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2781 if (offload_usecases[offload_uc_index] == uc_id) {
2782 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002783 break;
2784 }
2785 }
2786 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2787}
2788
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002789static void *offload_thread_loop(void *context)
2790{
2791 struct stream_out *out = (struct stream_out *) context;
2792 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002793 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002794
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002795 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2796 set_sched_policy(0, SP_FOREGROUND);
2797 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2798
2799 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002800 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002801 for (;;) {
2802 struct offload_cmd *cmd = NULL;
2803 stream_callback_event_t event;
2804 bool send_callback = false;
2805
2806 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2807 __func__, list_empty(&out->offload_cmd_list),
2808 out->offload_state);
2809 if (list_empty(&out->offload_cmd_list)) {
2810 ALOGV("%s SLEEPING", __func__);
2811 pthread_cond_wait(&out->offload_cond, &out->lock);
2812 ALOGV("%s RUNNING", __func__);
2813 continue;
2814 }
2815
2816 item = list_head(&out->offload_cmd_list);
2817 cmd = node_to_item(item, struct offload_cmd, node);
2818 list_remove(item);
2819
2820 ALOGVV("%s STATE %d CMD %d out->compr %p",
2821 __func__, out->offload_state, cmd->cmd, out->compr);
2822
2823 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2824 free(cmd);
2825 break;
2826 }
2827
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002828 // allow OFFLOAD_CMD_ERROR reporting during standby
2829 // this is needed to handle failures during compress_open
2830 // Note however that on a pause timeout, the stream is closed
2831 // and no offload usecase will be active. Therefore this
2832 // special case is needed for compress_open failures alone
2833 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2834 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002835 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002836 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002837 pthread_cond_signal(&out->cond);
2838 continue;
2839 }
2840 out->offload_thread_blocked = true;
2841 pthread_mutex_unlock(&out->lock);
2842 send_callback = false;
2843 switch(cmd->cmd) {
2844 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002845 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002846 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002847 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002848 send_callback = true;
2849 event = STREAM_CBK_EVENT_WRITE_READY;
2850 break;
2851 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002852 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302853 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002854 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302855 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002856 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302857 if (ret < 0)
2858 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302859 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302860 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002861 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002862 else
2863 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002864 if (-ENETRESET != ret && !(-EINTR == ret &&
2865 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302866 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302867 pthread_mutex_lock(&out->lock);
2868 out->send_new_metadata = 1;
2869 out->send_next_track_params = true;
2870 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302871 event = STREAM_CBK_EVENT_DRAIN_READY;
2872 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2873 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302874 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002875 break;
2876 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002877 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002878 ret = compress_drain(out->compr);
2879 ALOGD("copl(%p):out of compress_drain", out);
2880 // EINTR check avoids drain interruption due to SSR
2881 if (-ENETRESET != ret && !(-EINTR == ret &&
2882 CARD_STATUS_OFFLINE == out->card_status)) {
2883 send_callback = true;
2884 event = STREAM_CBK_EVENT_DRAIN_READY;
2885 } else
2886 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002887 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302888 case OFFLOAD_CMD_ERROR:
2889 ALOGD("copl(%p): sending error callback to AF", out);
2890 send_callback = true;
2891 event = STREAM_CBK_EVENT_ERROR;
2892 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002893 default:
2894 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2895 break;
2896 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002897 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002898 out->offload_thread_blocked = false;
2899 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002900 if (send_callback && out->client_callback) {
2901 ALOGVV("%s: sending client_callback event %d", __func__, event);
2902 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002903 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002904 free(cmd);
2905 }
2906
2907 pthread_cond_signal(&out->cond);
2908 while (!list_empty(&out->offload_cmd_list)) {
2909 item = list_head(&out->offload_cmd_list);
2910 list_remove(item);
2911 free(node_to_item(item, struct offload_cmd, node));
2912 }
2913 pthread_mutex_unlock(&out->lock);
2914
2915 return NULL;
2916}
2917
2918static int create_offload_callback_thread(struct stream_out *out)
2919{
2920 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2921 list_init(&out->offload_cmd_list);
2922 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2923 offload_thread_loop, out);
2924 return 0;
2925}
2926
2927static int destroy_offload_callback_thread(struct stream_out *out)
2928{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002929 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002930 stop_compressed_output_l(out);
2931 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2932
2933 pthread_mutex_unlock(&out->lock);
2934 pthread_join(out->offload_thread, (void **) NULL);
2935 pthread_cond_destroy(&out->offload_cond);
2936
2937 return 0;
2938}
2939
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002940static int stop_output_stream(struct stream_out *out)
2941{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302942 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002943 struct audio_usecase *uc_info;
2944 struct audio_device *adev = out->dev;
2945
Eric Laurent994a6932013-07-17 11:51:42 -07002946 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002947 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002948 uc_info = get_usecase_from_list(adev, out->usecase);
2949 if (uc_info == NULL) {
2950 ALOGE("%s: Could not find the usecase (%d) in the list",
2951 __func__, out->usecase);
2952 return -EINVAL;
2953 }
2954
Derek Chencdd17c72014-11-24 12:39:14 -08002955 if (uc_info->out_snd_device != SND_DEVICE_NONE) {
2956 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2957 ALOGE("%s: failed to stop ext hw plugin", __func__);
2958 }
2959
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002960 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302961 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002962 if (adev->visualizer_stop_output != NULL)
2963 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002964
2965 audio_extn_dts_remove_state_notifier_node(out->usecase);
2966
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002967 if (adev->offload_effects_stop_output != NULL)
2968 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2969 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002970
Arun Mirpuridbef0c72018-09-12 18:36:10 -07002971 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
2972 out->usecase == USECASE_INCALL_MUSIC_UPLINK2)
Arun Mirpurief53ce52018-09-11 18:00:09 -07002973 voice_set_device_mute_flag(adev, false);
2974
Eric Laurent150dbfe2013-02-27 14:31:02 -08002975 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002976 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002977
2978 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002979 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002981 if (is_offload_usecase(out->usecase)) {
2982 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2983 adev->dsp_bit_width_enforce_mode,
2984 false);
2985 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07002986 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2987 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
2988 false);
2989
2990 if (ret != 0)
2991 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
2992 /* default service interval was successfully updated,
2993 reopen USB backend with new service interval */
2994 ret = 0;
2995 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002996
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002997 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302998 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002999 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303000 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003001 ALOGV("Disable passthrough , reset mixer to pcm");
3002 /* NO_PASSTHROUGH */
3003 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003004 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003005 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3006 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003007
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303008 /* Must be called after removing the usecase from list */
3009 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303010 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303011
Manish Dewangan21a850a2017-08-14 12:03:55 +05303012 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003013 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3014 if (ret < 0)
3015 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3016 }
3017
Garmond Leung5fd0b552018-04-17 11:56:12 -07003018 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003019 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020 return ret;
3021}
3022
3023int start_output_stream(struct stream_out *out)
3024{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026 struct audio_usecase *uc_info;
3027 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003028 char mixer_ctl_name[128];
3029 struct mixer_ctl *ctl = NULL;
3030 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303031 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032
Haynes Mathew George380745d2017-10-04 15:27:45 -07003033 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003034 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3035 ret = -EINVAL;
3036 goto error_config;
3037 }
3038
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303039 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
3040 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
3041 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303042
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303043 if (CARD_STATUS_OFFLINE == out->card_status ||
3044 CARD_STATUS_OFFLINE == adev->card_status) {
3045 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303046 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303047 goto error_config;
3048 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303049
Arun Mirpuridbef0c72018-09-12 18:36:10 -07003050 //Update incall music usecase to reflect correct voice session
3051 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3052 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3053 if (ret != 0) {
3054 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3055 __func__, ret);
3056 goto error_config;
3057 }
3058 }
3059
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303060 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
3061 if (!audio_extn_a2dp_is_ready()) {
3062 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303063 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303064 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303065 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3066 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3067 ret = -EAGAIN;
3068 goto error_config;
3069 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303070 }
3071 }
3072 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303073 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3074 if (!adev->bt_sco_on) {
3075 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3076 //combo usecase just by pass a2dp
3077 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3078 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3079 } else {
3080 ALOGE("%s: SCO profile is not ready, return error", __func__);
3081 ret = -EAGAIN;
3082 goto error_config;
3083 }
3084 }
3085 }
3086
Eric Laurentb23d5282013-05-14 15:27:20 -07003087 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088 if (out->pcm_device_id < 0) {
3089 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3090 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003091 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003092 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003093 }
3094
3095 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003096
3097 if (!uc_info) {
3098 ret = -ENOMEM;
3099 goto error_config;
3100 }
3101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102 uc_info->id = out->usecase;
3103 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003104 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003105 uc_info->devices = out->devices;
3106 uc_info->in_snd_device = SND_DEVICE_NONE;
3107 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003108
3109 /* This must be called before adding this usecase to the list */
3110 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3111 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3112 /* USB backend is not reopened immediately.
3113 This is eventually done as part of select_devices */
3114 }
3115
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003116 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303118 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3119 adev->perf_lock_opts,
3120 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303121
3122 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303123 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303124 if (audio_extn_passthru_is_enabled() &&
3125 audio_extn_passthru_is_passthrough_stream(out)) {
3126 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303127 }
3128 }
3129
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303130 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3131 (!audio_extn_a2dp_is_ready())) {
3132 if (!a2dp_combo) {
3133 check_a2dp_restore_l(adev, out, false);
3134 } else {
3135 audio_devices_t dev = out->devices;
3136 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3137 select_devices(adev, out->usecase);
3138 out->devices = dev;
3139 }
3140 } else {
3141 select_devices(adev, out->usecase);
3142 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003143
Arun Mirpuridbef0c72018-09-12 18:36:10 -07003144 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3145 out->usecase == USECASE_INCALL_MUSIC_UPLINK2)
Arun Mirpurief53ce52018-09-11 18:00:09 -07003146 voice_set_device_mute_flag(adev, true);
3147
Derek Chencdd17c72014-11-24 12:39:14 -08003148 if (uc_info->out_snd_device != SND_DEVICE_NONE) {
3149 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3150 ALOGE("%s: failed to start ext hw plugin", __func__);
3151 }
3152
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003153 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3154 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003155
3156 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuriebe78a72018-10-04 18:23:46 -07003157 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003158 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3159 ALOGE("%s: pcm stream not ready", __func__);
3160 goto error_open;
3161 }
3162 ret = pcm_start(out->pcm);
3163 if (ret < 0) {
3164 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3165 goto error_open;
3166 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07003167 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003168 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003169 unsigned int flags = PCM_OUT;
3170 unsigned int pcm_open_retry_count = 0;
3171 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3172 flags |= PCM_MMAP | PCM_NOIRQ;
3173 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003174 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003175 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003176 } else
3177 flags |= PCM_MONOTONIC;
3178
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003179 if ((adev->vr_audio_mode_enabled) &&
3180 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3181 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3182 "PCM_Dev %d Topology", out->pcm_device_id);
3183 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3184 if (!ctl) {
3185 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3186 __func__, mixer_ctl_name);
3187 } else {
3188 //if success use ULLPP
3189 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3190 __func__, mixer_ctl_name, out->pcm_device_id);
3191 //There is a still a possibility that some sessions
3192 // that request for FAST|RAW when 3D audio is active
3193 //can go through ULLPP. Ideally we expects apps to
3194 //listen to audio focus and stop concurrent playback
3195 //Also, we will look for mode flag (voice_in_communication)
3196 //before enabling the realtime flag.
3197 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3198 }
3199 }
3200
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003201 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003202 ATRACE_BEGIN("pcm_open");
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003203 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3204 flags, &out->config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003205 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05303206 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
3207 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3208 out->card_status = CARD_STATUS_OFFLINE;
3209 adev->card_status = CARD_STATUS_OFFLINE;
3210 ret = -EIO;
3211 goto error_open;
3212 }
3213
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003214 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3215 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3216 if (out->pcm != NULL) {
3217 pcm_close(out->pcm);
3218 out->pcm = NULL;
3219 }
3220 if (pcm_open_retry_count-- == 0) {
3221 ret = -EIO;
3222 goto error_open;
3223 }
3224 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3225 continue;
3226 }
3227 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003228 }
Surendar Karka5a18a7a2018-04-26 11:28:38 +05303229 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3230 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003231
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003232 ALOGV("%s: pcm_prepare", __func__);
3233 if (pcm_is_ready(out->pcm)) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003234 ATRACE_BEGIN("pcm_prepare");
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003235 ret = pcm_prepare(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003236 ATRACE_END();
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003237 if (ret < 0) {
3238 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3239 pcm_close(out->pcm);
3240 out->pcm = NULL;
3241 goto error_open;
3242 }
3243 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08003244 // apply volume for voip playback after path is set up
3245 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3246 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003247 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003248 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303249 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003250 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3251 adev->dsp_bit_width_enforce_mode,
3252 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003253 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003254 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003255 out->compr = compress_open(adev->snd_card,
3256 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003257 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003258 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05303259 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
3260 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3261 adev->card_status = CARD_STATUS_OFFLINE;
3262 out->card_status = CARD_STATUS_OFFLINE;
3263 ret = -EIO;
3264 goto error_open;
3265 }
3266
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003267 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003268 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003269 compress_close(out->compr);
3270 out->compr = NULL;
3271 ret = -EIO;
3272 goto error_open;
3273 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303274 /* compress_open sends params of the track, so reset the flag here */
3275 out->is_compr_metadata_avail = false;
3276
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003277 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003278 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003279
Fred Oh3f43e742015-03-04 18:42:34 -08003280 /* Since small bufs uses blocking writes, a write will be blocked
3281 for the default max poll time (20s) in the event of an SSR.
3282 Reduce the poll time to observe and deal with SSR faster.
3283 */
Ashish Jain5106d362016-05-11 19:23:33 +05303284 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003285 compress_set_max_poll_wait(out->compr, 1000);
3286 }
3287
Manish Dewangan69426c82017-01-30 17:35:36 +05303288 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303289 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303290
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003291 audio_extn_dts_create_state_notifier_node(out->usecase);
3292 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3293 popcount(out->channel_mask),
3294 out->playback_started);
3295
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003296#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303297 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003298 audio_extn_dolby_send_ddp_endp_params(adev);
3299#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303300 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3301 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003302 if (adev->visualizer_start_output != NULL)
3303 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3304 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303305 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003306 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003307 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003308 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003309
3310 if (ret == 0) {
3311 register_out_stream(out);
3312 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003313 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3314 ALOGE("%s: pcm stream not ready", __func__);
3315 goto error_open;
3316 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003317 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003318 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003319 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003320 if (ret < 0)
3321 goto error_open;
3322 }
3323 }
3324
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303325 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003326 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003327
Manish Dewangan21a850a2017-08-14 12:03:55 +05303328 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003329 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003330 if (ret < 0)
3331 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3332 }
3333
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003334 // consider a scenario where on pause lower layers are tear down.
3335 // so on resume, swap mixer control need to be sent only when
3336 // backend is active, hence rather than sending from enable device
3337 // sending it from start of streamtream
3338
3339 platform_set_swap_channels(adev, true);
3340
Haynes Mathew George380745d2017-10-04 15:27:45 -07003341 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003342 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003343error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303344 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003346error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303347 /*
3348 * sleep 50ms to allow sufficient time for kernel
3349 * drivers to recover incases like SSR.
3350 */
3351 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003352 ATRACE_END();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003353 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354}
3355
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356static int check_input_parameters(uint32_t sample_rate,
3357 audio_format_t format,
3358 int channel_count)
3359{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003360 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003361
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303362 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3363 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3364 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003365 !voice_extn_compress_voip_is_format_supported(format) &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003366 !audio_extn_compr_cap_format_supported(format))
3367 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003368
3369 switch (channel_count) {
3370 case 1:
3371 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303372 case 3:
3373 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003374 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003375 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003376 break;
3377 default:
3378 ret = -EINVAL;
3379 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380
3381 switch (sample_rate) {
3382 case 8000:
3383 case 11025:
3384 case 12000:
3385 case 16000:
3386 case 22050:
3387 case 24000:
3388 case 32000:
3389 case 44100:
3390 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003391 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303392 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003393 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303394 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395 break;
3396 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003397 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003398 }
3399
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003400 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401}
3402
Naresh Tanniru04f71882018-06-26 17:46:22 +05303403
3404/** Add a value in a list if not already present.
3405 * @return true if value was successfully inserted or already present,
3406 * false if the list is full and does not contain the value.
3407 */
3408static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3409 for (size_t i = 0; i < list_length; i++) {
3410 if (list[i] == value) return true; // value is already present
3411 if (list[i] == 0) { // no values in this slot
3412 list[i] = value;
3413 return true; // value inserted
3414 }
3415 }
3416 return false; // could not insert value
3417}
3418
3419/** Add channel_mask in supported_channel_masks if not already present.
3420 * @return true if channel_mask was successfully inserted or already present,
3421 * false if supported_channel_masks is full and does not contain channel_mask.
3422 */
3423static void register_channel_mask(audio_channel_mask_t channel_mask,
3424 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3425 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3426 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3427}
3428
3429/** Add format in supported_formats if not already present.
3430 * @return true if format was successfully inserted or already present,
3431 * false if supported_formats is full and does not contain format.
3432 */
3433static void register_format(audio_format_t format,
3434 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3435 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3436 "%s: stream can not declare supporting its format %x", __func__, format);
3437}
3438/** Add sample_rate in supported_sample_rates if not already present.
3439 * @return true if sample_rate was successfully inserted or already present,
3440 * false if supported_sample_rates is full and does not contain sample_rate.
3441 */
3442static void register_sample_rate(uint32_t sample_rate,
3443 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3444 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3445 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3446}
3447
Karthikeyan Mani35531922018-11-07 15:44:13 -08003448static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3449{
3450 uint32_t high = num1, low = num2, temp = 0;
3451
3452 if (!num1 || !num2)
3453 return 0;
3454
3455 if (num1 < num2) {
3456 high = num2;
3457 low = num1;
3458 }
3459
3460 while (low != 0) {
3461 temp = low;
3462 low = high % low;
3463 high = temp;
3464 }
3465 return (num1 * num2)/high;
3466}
3467
3468static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3469{
3470 uint32_t remainder = 0;
3471
3472 if (!multiplier)
3473 return num;
3474
3475 remainder = num % multiplier;
3476 if (remainder)
3477 num += (multiplier - remainder);
3478
3479 return num;
3480}
3481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003482static size_t get_input_buffer_size(uint32_t sample_rate,
3483 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003484 int channel_count,
3485 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486{
3487 size_t size = 0;
Karthikeyan Mani35531922018-11-07 15:44:13 -08003488 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003490 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3491 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003492
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003493 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003494 if (is_low_latency)
3495 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303496
Karthikeyan Mani35531922018-11-07 15:44:13 -08003497 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
3498 size *= bytes_per_period_sample;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003500 /* make sure the size is multiple of 32 bytes
3501 * At 48 kHz mono 16-bit PCM:
3502 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3503 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Mani35531922018-11-07 15:44:13 -08003504 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003505 */
Karthikeyan Mani35531922018-11-07 15:44:13 -08003506 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003507
3508 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509}
3510
Ashish Jain058165c2016-09-28 23:18:48 +05303511static size_t get_output_period_size(uint32_t sample_rate,
3512 audio_format_t format,
3513 int channel_count,
3514 int duration /*in millisecs*/)
3515{
3516 size_t size = 0;
3517 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3518
3519 if ((duration == 0) || (sample_rate == 0) ||
3520 (bytes_per_sample == 0) || (channel_count == 0)) {
3521 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3522 bytes_per_sample, channel_count);
3523 return -EINVAL;
3524 }
3525
3526 size = (sample_rate *
3527 duration *
3528 bytes_per_sample *
3529 channel_count) / 1000;
3530 /*
3531 * To have same PCM samples for all channels, the buffer size requires to
3532 * be multiple of (number of channels * bytes per sample)
3533 * For writes to succeed, the buffer must be written at address which is multiple of 32
3534 */
3535 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3536
3537 return (size/(channel_count * bytes_per_sample));
3538}
3539
Zhou Song48453a02018-01-10 17:50:59 +08003540static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303541{
3542 uint64_t actual_frames_rendered = 0;
3543 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3544
3545 /* This adjustment accounts for buffering after app processor.
3546 * It is based on estimated DSP latency per use case, rather than exact.
3547 */
3548 int64_t platform_latency = platform_render_latency(out->usecase) *
3549 out->sample_rate / 1000000LL;
3550
Zhou Song48453a02018-01-10 17:50:59 +08003551 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303552 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3553 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3554 * hence only estimate.
3555 */
3556 int64_t signed_frames = out->written - kernel_buffer_size;
3557
3558 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3559
Zhou Song48453a02018-01-10 17:50:59 +08003560 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303561 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003562 if (timestamp != NULL )
3563 *timestamp = out->writeAt;
3564 } else if (timestamp != NULL) {
3565 clock_gettime(CLOCK_MONOTONIC, timestamp);
3566 }
3567 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303568
3569 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3570 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3571 (long long int)out->written, (int)kernel_buffer_size,
3572 audio_bytes_per_sample(out->compr_config.codec->format),
3573 popcount(out->channel_mask));
3574
3575 return actual_frames_rendered;
3576}
3577
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3579{
3580 struct stream_out *out = (struct stream_out *)stream;
3581
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003582 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003583}
3584
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003585static int out_set_sample_rate(struct audio_stream *stream __unused,
3586 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587{
3588 return -ENOSYS;
3589}
3590
3591static size_t out_get_buffer_size(const struct audio_stream *stream)
3592{
3593 struct stream_out *out = (struct stream_out *)stream;
3594
Varun Balaraje49253e2017-07-06 19:48:56 +05303595 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303596 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303597 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303598 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3599 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3600 else
3601 return out->compr_config.fragment_size;
3602 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003603 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003604 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3605 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 +05303606 else if (is_offload_usecase(out->usecase) &&
3607 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303608 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003609
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003610 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003611 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612}
3613
3614static uint32_t out_get_channels(const struct audio_stream *stream)
3615{
3616 struct stream_out *out = (struct stream_out *)stream;
3617
3618 return out->channel_mask;
3619}
3620
3621static audio_format_t out_get_format(const struct audio_stream *stream)
3622{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003623 struct stream_out *out = (struct stream_out *)stream;
3624
3625 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626}
3627
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003628static int out_set_format(struct audio_stream *stream __unused,
3629 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630{
3631 return -ENOSYS;
3632}
3633
3634static int out_standby(struct audio_stream *stream)
3635{
3636 struct stream_out *out = (struct stream_out *)stream;
3637 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003638 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003639
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303640 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3641 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003643 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003644 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003645 if (adev->adm_deregister_stream)
3646 adev->adm_deregister_stream(adev->adm_data, out->handle);
3647
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003648 if (is_offload_usecase(out->usecase))
3649 stop_compressed_output_l(out);
3650
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003651 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003653 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3654 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303655 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003656 pthread_mutex_unlock(&adev->lock);
3657 pthread_mutex_unlock(&out->lock);
3658 ALOGD("VOIP output entered standby");
3659 return 0;
3660 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003661 if (out->pcm) {
3662 pcm_close(out->pcm);
3663 out->pcm = NULL;
3664 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003665 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3666 do_stop = out->playback_started;
3667 out->playback_started = false;
3668 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003669 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003670 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303671 out->send_next_track_params = false;
3672 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003673 out->gapless_mdata.encoder_delay = 0;
3674 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003675 if (out->compr != NULL) {
3676 compress_close(out->compr);
3677 out->compr = NULL;
3678 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003679 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003680 if (do_stop) {
3681 stop_output_stream(out);
3682 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003683 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684 }
3685 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303686 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687 return 0;
3688}
3689
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303690static int out_on_error(struct audio_stream *stream)
3691{
3692 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003693 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303694
3695 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003696 // always send CMD_ERROR for offload streams, this
3697 // is needed e.g. when SSR happens within compress_open
3698 // since the stream is active, offload_callback_thread is also active.
3699 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3700 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003701 }
3702 pthread_mutex_unlock(&out->lock);
3703
3704 status = out_standby(&out->stream.common);
3705
3706 lock_output_stream(out);
3707 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003708 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303709 }
3710 pthread_mutex_unlock(&out->lock);
3711
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003712 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303713}
3714
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303715/*
3716 *standby implementation without locks, assumes that the callee already
3717 *has taken adev and out lock.
3718 */
3719int out_standby_l(struct audio_stream *stream)
3720{
3721 struct stream_out *out = (struct stream_out *)stream;
3722 struct audio_device *adev = out->dev;
3723
3724 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3725 stream, out->usecase, use_case_table[out->usecase]);
3726
3727 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003728 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303729 if (adev->adm_deregister_stream)
3730 adev->adm_deregister_stream(adev->adm_data, out->handle);
3731
3732 if (is_offload_usecase(out->usecase))
3733 stop_compressed_output_l(out);
3734
3735 out->standby = true;
3736 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3737 voice_extn_compress_voip_close_output_stream(stream);
3738 out->started = 0;
3739 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003740 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303741 return 0;
3742 } else if (!is_offload_usecase(out->usecase)) {
3743 if (out->pcm) {
3744 pcm_close(out->pcm);
3745 out->pcm = NULL;
3746 }
3747 } else {
3748 ALOGD("copl(%p):standby", out);
3749 out->send_next_track_params = false;
3750 out->is_compr_metadata_avail = false;
3751 out->gapless_mdata.encoder_delay = 0;
3752 out->gapless_mdata.encoder_padding = 0;
3753 if (out->compr != NULL) {
3754 compress_close(out->compr);
3755 out->compr = NULL;
3756 }
3757 }
3758 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003759 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303760 }
3761 ALOGD("%s: exit", __func__);
3762 return 0;
3763}
3764
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003765static int out_dump(const struct audio_stream *stream __unused,
3766 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767{
3768 return 0;
3769}
3770
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003771static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3772{
3773 int ret = 0;
3774 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003775
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003776 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003777 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003778 return -EINVAL;
3779 }
3780
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303781 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003782
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003783 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3784 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303785 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003786 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003787 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3788 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303789 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003790 }
3791
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003792 ALOGV("%s new encoder delay %u and padding %u", __func__,
3793 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3794
3795 return 0;
3796}
3797
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003798static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3799{
3800 return out == adev->primary_output || out == adev->voice_tx_output;
3801}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003802
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303803// note: this call is safe only if the stream_cb is
3804// removed first in close_output_stream (as is done now).
3805static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3806{
3807 if (!stream || !parms)
3808 return;
3809
3810 struct stream_out *out = (struct stream_out *)stream;
3811 struct audio_device *adev = out->dev;
3812
3813 card_status_t status;
3814 int card;
3815 if (parse_snd_card_status(parms, &card, &status) < 0)
3816 return;
3817
3818 pthread_mutex_lock(&adev->lock);
3819 bool valid_cb = (card == adev->snd_card);
3820 pthread_mutex_unlock(&adev->lock);
3821
3822 if (!valid_cb)
3823 return;
3824
3825 lock_output_stream(out);
3826 if (out->card_status != status)
3827 out->card_status = status;
3828 pthread_mutex_unlock(&out->lock);
3829
3830 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3831 use_case_table[out->usecase],
3832 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3833
3834 if (status == CARD_STATUS_OFFLINE)
3835 out_on_error(stream);
3836
3837 return;
3838}
3839
Kevin Rocardfce19002017-08-07 19:21:36 -07003840static int get_alive_usb_card(struct str_parms* parms) {
3841 int card;
3842 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
3843 !audio_extn_usb_alive(card)) {
3844 return card;
3845 }
3846 return -ENODEV;
3847}
3848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3850{
3851 struct stream_out *out = (struct stream_out *)stream;
3852 struct audio_device *adev = out->dev;
3853 struct str_parms *parms;
3854 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003855 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303856 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003857 bool reconfig = false;
3858 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859
sangwoobc677242013-08-08 16:53:43 +09003860 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003861 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003862 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303863 if (!parms)
3864 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003865 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3866 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003867 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003868 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003869 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003871 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003872 * When HDMI cable is unplugged the music playback is paused and
3873 * the policy manager sends routing=0. But the audioflinger continues
3874 * to write data until standby time (3sec). As the HDMI core is
3875 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003876 * Avoid this by routing audio to speaker until standby.
3877 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003878 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3879 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303880 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003881 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3882 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003883 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303884 /*
3885 * When A2DP is disconnected the
3886 * music playback is paused and the policy manager sends routing=0
3887 * But the audioflingercontinues to write data until standby time
3888 * (3sec). As BT is turned off, the write gets blocked.
3889 * Avoid this by routing audio to speaker until standby.
3890 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003891 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07003892 (val == AUDIO_DEVICE_NONE) &&
3893 !audio_extn_a2dp_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303894 val = AUDIO_DEVICE_OUT_SPEAKER;
3895 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05303896 /*
3897 * When USB headset is disconnected the music platback paused
3898 * and the policy manager send routing=0. But if the USB is connected
3899 * back before the standby time, AFE is not closed and opened
3900 * when USB is connected back. So routing to speker will guarantee
3901 * AFE reconfiguration and AFE will be opend once USB is connected again
3902 */
3903 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
3904 (val == AUDIO_DEVICE_NONE) &&
3905 !audio_extn_usb_connected(parms)) {
3906 val = AUDIO_DEVICE_OUT_SPEAKER;
3907 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303908 /* To avoid a2dp to sco overlapping / BT device improper state
3909 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303910 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303911 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3912 if (!audio_extn_a2dp_is_ready()) {
3913 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3914 //combo usecase just by pass a2dp
3915 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303916 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303917 } else {
3918 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3919 /* update device to a2dp and don't route as BT returned error
3920 * However it is still possible a2dp routing called because
3921 * of current active device disconnection (like wired headset)
3922 */
3923 out->devices = val;
3924 pthread_mutex_unlock(&out->lock);
3925 pthread_mutex_unlock(&adev->lock);
3926 goto error;
3927 }
3928 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303929 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003930
3931 audio_devices_t new_dev = val;
3932
3933 // Workaround: If routing to an non existing usb device, fail gracefully
3934 // The routing request will otherwise block during 10 second
3935 int card;
3936 if (audio_is_usb_out_device(new_dev) &&
3937 (card = get_alive_usb_card(parms)) >= 0) {
3938
3939 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
3940 pthread_mutex_unlock(&adev->lock);
3941 pthread_mutex_unlock(&out->lock);
3942 ret = -ENOSYS;
3943 goto routing_fail;
3944 }
3945
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003946 /*
3947 * select_devices() call below switches all the usecases on the same
3948 * backend to the new device. Refer to check_usecases_codec_backend() in
3949 * the select_devices(). But how do we undo this?
3950 *
3951 * For example, music playback is active on headset (deep-buffer usecase)
3952 * and if we go to ringtones and select a ringtone, low-latency usecase
3953 * will be started on headset+speaker. As we can't enable headset+speaker
3954 * and headset devices at the same time, select_devices() switches the music
3955 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3956 * So when the ringtone playback is completed, how do we undo the same?
3957 *
3958 * We are relying on the out_set_parameters() call on deep-buffer output,
3959 * once the ringtone playback is ended.
3960 * NOTE: We should not check if the current devices are same as new devices.
3961 * Because select_devices() must be called to switch back the music
3962 * playback to headset.
3963 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003964 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003965 audio_devices_t new_dev = val;
3966 bool same_dev = out->devices == new_dev;
3967 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003968
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003969 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08003970 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003971 if (adev->mode == AUDIO_MODE_IN_CALL) {
3972 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003973 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3974 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
3975 audio_extn_usb_set_service_interval(true /*playback*/,
3976 service_interval,
3977 &reconfig);
3978 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
3979 }
3980 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003981 }
3982 } else {
3983 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003984 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003985 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003986 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003987
3988 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003989 if (!same_dev) {
3990 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303991 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3992 adev->perf_lock_opts,
3993 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003994 if (adev->adm_on_routing_change)
3995 adev->adm_on_routing_change(adev->adm_data,
3996 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003997 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303998 if (!bypass_a2dp) {
3999 select_devices(adev, out->usecase);
4000 } else {
4001 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
4002 select_devices(adev, out->usecase);
4003 out->devices = new_dev;
4004 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004005
4006 if (!same_dev) {
4007 // on device switch force swap, lower functions will make sure
4008 // to check if swap is allowed or not.
4009 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304010 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004011 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304012 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4013 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08004014 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304015 pthread_mutex_lock(&out->compr_mute_lock);
4016 out->a2dp_compress_mute = false;
4017 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4018 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004019 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4020 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304021 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004022 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004023 }
4024
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004025 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004026 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004027 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004028 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004029
4030 if (out == adev->primary_output) {
4031 pthread_mutex_lock(&adev->lock);
4032 audio_extn_set_parameters(adev, parms);
4033 pthread_mutex_unlock(&adev->lock);
4034 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004035 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004036 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004037 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004038
4039 audio_extn_dts_create_state_notifier_node(out->usecase);
4040 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4041 popcount(out->channel_mask),
4042 out->playback_started);
4043
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004044 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004045 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004046
Surendar Karka5a18a7a2018-04-26 11:28:38 +05304047 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4048 sizeof(value));
4049 if (err >= 0) {
4050 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4051 audio_extn_send_dual_mono_mixing_coefficients(out);
4052 }
4053
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304054 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4055 if (err >= 0) {
4056 strlcpy(out->profile, value, sizeof(out->profile));
4057 ALOGV("updating stream profile with value '%s'", out->profile);
4058 lock_output_stream(out);
4059 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4060 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004061 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304062 out->sample_rate, out->bit_width,
4063 out->channel_mask, out->profile,
4064 &out->app_type_cfg);
4065 pthread_mutex_unlock(&out->lock);
4066 }
4067
Alexy Joseph98988832017-01-13 14:56:59 -08004068 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004069 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4070 // and vendor.audio.hal.output.suspend.supported is set to true
4071 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004072 //check suspend parameter only for low latency and if the property
4073 //is enabled
4074 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4075 ALOGI("%s: got suspend_playback %s", __func__, value);
4076 lock_output_stream(out);
4077 if (!strncmp(value, "false", 5)) {
4078 //suspend_playback=false is supposed to set QOS value back to 75%
4079 //the mixer control sent with value Enable will achieve that
4080 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4081 } else if (!strncmp (value, "true", 4)) {
4082 //suspend_playback=true is supposed to remove QOS value
4083 //resetting the mixer control will set the default value
4084 //for the mixer control which is Disable and this removes the QOS vote
4085 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4086 } else {
4087 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4088 " got %s", __func__, value);
4089 ret = -1;
4090 }
4091
4092 if (ret != 0) {
4093 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4094 __func__, out->pm_qos_mixer_path, ret);
4095 }
4096
4097 pthread_mutex_unlock(&out->lock);
4098 }
4099 }
4100 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004101 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304102error:
Eric Laurent994a6932013-07-17 11:51:42 -07004103 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004104 return ret;
4105}
4106
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004107static bool stream_get_parameter_channels(struct str_parms *query,
4108 struct str_parms *reply,
4109 audio_channel_mask_t *supported_channel_masks) {
4110 int ret = -1;
4111 char value[512];
4112 bool first = true;
4113 size_t i, j;
4114
4115 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4116 ret = 0;
4117 value[0] = '\0';
4118 i = 0;
4119 while (supported_channel_masks[i] != 0) {
4120 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4121 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4122 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304123 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004124
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304125 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004126 first = false;
4127 break;
4128 }
4129 }
4130 i++;
4131 }
4132 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4133 }
4134 return ret == 0;
4135}
4136
4137static bool stream_get_parameter_formats(struct str_parms *query,
4138 struct str_parms *reply,
4139 audio_format_t *supported_formats) {
4140 int ret = -1;
4141 char value[256];
4142 size_t i, j;
4143 bool first = true;
4144
4145 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4146 ret = 0;
4147 value[0] = '\0';
4148 i = 0;
4149 while (supported_formats[i] != 0) {
4150 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4151 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4152 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304153 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004154 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304155 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004156 first = false;
4157 break;
4158 }
4159 }
4160 i++;
4161 }
4162 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4163 }
4164 return ret == 0;
4165}
4166
4167static bool stream_get_parameter_rates(struct str_parms *query,
4168 struct str_parms *reply,
4169 uint32_t *supported_sample_rates) {
4170
4171 int i;
4172 char value[256];
4173 int ret = -1;
4174 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4175 ret = 0;
4176 value[0] = '\0';
4177 i=0;
4178 int cursor = 0;
4179 while (supported_sample_rates[i]) {
4180 int avail = sizeof(value) - cursor;
4181 ret = snprintf(value + cursor, avail, "%s%d",
4182 cursor > 0 ? "|" : "",
4183 supported_sample_rates[i]);
4184 if (ret < 0 || ret >= avail) {
4185 // if cursor is at the last element of the array
4186 // overwrite with \0 is duplicate work as
4187 // snprintf already put a \0 in place.
4188 // else
4189 // we had space to write the '|' at value[cursor]
4190 // (which will be overwritten) or no space to fill
4191 // the first element (=> cursor == 0)
4192 value[cursor] = '\0';
4193 break;
4194 }
4195 cursor += ret;
4196 ++i;
4197 }
4198 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4199 value);
4200 }
4201 return ret >= 0;
4202}
4203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004204static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4205{
4206 struct stream_out *out = (struct stream_out *)stream;
4207 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004208 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004209 char value[256];
4210 struct str_parms *reply = str_parms_create();
4211 size_t i, j;
4212 int ret;
4213 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004214
4215 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004216 if (reply) {
4217 str_parms_destroy(reply);
4218 }
4219 if (query) {
4220 str_parms_destroy(query);
4221 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004222 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4223 return NULL;
4224 }
4225
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004226 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004227 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4228 if (ret >= 0) {
4229 value[0] = '\0';
4230 i = 0;
4231 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004232 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4233 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004234 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004235 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004236 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004237 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004238 first = false;
4239 break;
4240 }
4241 }
4242 i++;
4243 }
4244 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4245 str = str_parms_to_str(reply);
4246 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004247 voice_extn_out_get_parameters(out, query, reply);
4248 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004249 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004250
Alexy Joseph62142aa2015-11-16 15:10:34 -08004251
4252 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4253 if (ret >= 0) {
4254 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304255 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4256 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004257 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304258 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004259 } else {
4260 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304261 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004262 }
4263 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004264 if (str)
4265 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004266 str = str_parms_to_str(reply);
4267 }
4268
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004269 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4270 if (ret >= 0) {
4271 value[0] = '\0';
4272 i = 0;
4273 first = true;
4274 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004275 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4276 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004277 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004278 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004279 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004280 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004281 first = false;
4282 break;
4283 }
4284 }
4285 i++;
4286 }
4287 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004288 if (str)
4289 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004290 str = str_parms_to_str(reply);
4291 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004292
4293 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4294 if (ret >= 0) {
4295 value[0] = '\0';
4296 i = 0;
4297 first = true;
4298 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004299 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4300 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004301 if (!first) {
4302 strlcat(value, "|", sizeof(value));
4303 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004304 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004305 first = false;
4306 break;
4307 }
4308 }
4309 i++;
4310 }
4311 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4312 if (str)
4313 free(str);
4314 str = str_parms_to_str(reply);
4315 }
4316
Alexy Joseph98988832017-01-13 14:56:59 -08004317 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4318 //only low latency track supports suspend_resume
4319 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004320 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004321 if (str)
4322 free(str);
4323 str = str_parms_to_str(reply);
4324 }
4325
4326
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004327 str_parms_destroy(query);
4328 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004329 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004330 return str;
4331}
4332
4333static uint32_t out_get_latency(const struct audio_stream_out *stream)
4334{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004335 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004336 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004337 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004338
Alexy Josephaa54c872014-12-03 02:46:47 -08004339 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304340 lock_output_stream(out);
4341 latency = audio_extn_utils_compress_get_dsp_latency(out);
4342 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004343 } else if ((out->realtime) ||
4344 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004345 // since the buffer won't be filled up faster than realtime,
4346 // return a smaller number
4347 if (out->config.rate)
4348 period_ms = (out->af_period_multiplier * out->config.period_size *
4349 1000) / (out->config.rate);
4350 else
4351 period_ms = 0;
4352 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004353 } else {
4354 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004355 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004356 }
4357
yidongh0515e042017-07-06 15:00:34 +08004358 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004359 latency += audio_extn_a2dp_get_encoder_latency();
4360
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304361 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004362 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004363}
4364
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304365static float AmpToDb(float amplification)
4366{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304367 float db = DSD_VOLUME_MIN_DB;
4368 if (amplification > 0) {
4369 db = 20 * log10(amplification);
4370 if(db < DSD_VOLUME_MIN_DB)
4371 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304372 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304373 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304374}
4375
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004376static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4377 float right)
4378{
4379 struct stream_out *out = (struct stream_out *)stream;
4380 long volume = 0;
4381 char mixer_ctl_name[128] = "";
4382 struct audio_device *adev = out->dev;
4383 struct mixer_ctl *ctl = NULL;
4384 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4385 PCM_PLAYBACK);
4386
4387 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4388 "Playback %d Volume", pcm_device_id);
4389 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4390 if (!ctl) {
4391 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4392 __func__, mixer_ctl_name);
4393 return -EINVAL;
4394 }
4395 if (left != right)
4396 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4397 __func__, left, right);
4398 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4399 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4400 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4401 __func__, mixer_ctl_name, volume);
4402 return -EINVAL;
4403 }
4404 return 0;
4405}
4406
4407
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304408static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4409 float right)
4410{
4411 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304412 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304413 char mixer_ctl_name[128];
4414 struct audio_device *adev = out->dev;
4415 struct mixer_ctl *ctl;
4416 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4417 PCM_PLAYBACK);
4418
4419 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4420 "Compress Playback %d Volume", pcm_device_id);
4421 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4422 if (!ctl) {
4423 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4424 __func__, mixer_ctl_name);
4425 return -EINVAL;
4426 }
4427 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4428 __func__, mixer_ctl_name, left, right);
4429 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4430 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4431 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4432
4433 return 0;
4434}
4435
Zhou Song2b8f28f2017-09-11 10:51:38 +08004436static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4437 float right)
4438{
4439 struct stream_out *out = (struct stream_out *)stream;
4440 char mixer_ctl_name[] = "App Type Gain";
4441 struct audio_device *adev = out->dev;
4442 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304443 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004444
4445 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4446 if (!ctl) {
4447 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4448 __func__, mixer_ctl_name);
4449 return -EINVAL;
4450 }
4451
4452 set_values[0] = 0; //0: Rx Session 1:Tx Session
4453 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304454 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4455 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004456
4457 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4458 return 0;
4459}
4460
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004461static int out_set_volume(struct audio_stream_out *stream, float left,
4462 float right)
4463{
Eric Laurenta9024de2013-04-04 09:19:12 -07004464 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004465 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304466 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004467
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004468 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
4469
Eric Laurenta9024de2013-04-04 09:19:12 -07004470 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4471 /* only take left channel into account: the API is for stereo anyway */
4472 out->muted = (left == 0.0f);
4473 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004474 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304475 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004476 /*
4477 * Set mute or umute on HDMI passthrough stream.
4478 * Only take left channel into account.
4479 * Mute is 0 and unmute 1
4480 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304481 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304482 } else if (out->format == AUDIO_FORMAT_DSD){
4483 char mixer_ctl_name[128] = "DSD Volume";
4484 struct audio_device *adev = out->dev;
4485 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4486
4487 if (!ctl) {
4488 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4489 __func__, mixer_ctl_name);
4490 return -EINVAL;
4491 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304492 volume[0] = (long)(AmpToDb(left));
4493 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304494 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4495 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004496 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304497 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004498 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304499 if (!out->a2dp_compress_mute)
4500 ret = out_set_compr_volume(stream, left, right);
4501 out->volume_l = left;
4502 out->volume_r = right;
4503 pthread_mutex_unlock(&out->compr_mute_lock);
4504 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004505 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004506 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004507 if (!out->standby)
4508 ret = out_set_voip_volume(stream, left, right);
4509 out->volume_l = left;
4510 out->volume_r = right;
4511 return ret;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004512 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4513 ALOGV("%s: MMAP set volume called", __func__);
4514 if (!out->standby)
4515 ret = out_set_mmap_volume(stream, left, right);
4516 out->volume_l = left;
4517 out->volume_r = right;
4518 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004519 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004520
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004521 return -ENOSYS;
4522}
4523
Zhou Songc9672822017-08-16 16:01:39 +08004524static void update_frames_written(struct stream_out *out, size_t bytes)
4525{
4526 size_t bpf = 0;
4527
4528 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4529 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4530 bpf = 1;
4531 else if (!is_offload_usecase(out->usecase))
4532 bpf = audio_bytes_per_sample(out->format) *
4533 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004534
4535 pthread_mutex_lock(&out->position_query_lock);
4536 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004537 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004538 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4539 }
4540 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004541}
4542
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004543static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4544 size_t bytes)
4545{
4546 struct stream_out *out = (struct stream_out *)stream;
4547 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004548 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304549 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004550 const size_t frame_size = audio_stream_out_frame_size(stream);
4551 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004552
Haynes Mathew George380745d2017-10-04 15:27:45 -07004553 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004554 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304555
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304556 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004557
Dhananjay Kumarac341582017-02-23 23:42:25 +05304558 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304559 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304560 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4561 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004562 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304563 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304564 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304565 ALOGD(" %s: sound card is not active/SSR state", __func__);
4566 ret= -EIO;
4567 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304568 }
4569 }
4570
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304571 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304572 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304573 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304574 goto exit;
4575 }
4576
Haynes Mathew George16081042017-05-31 17:16:49 -07004577 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4578 ret = -EINVAL;
4579 goto exit;
4580 }
4581
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304582 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4583 !out->is_iec61937_info_available) {
4584
4585 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4586 out->is_iec61937_info_available = true;
4587 } else if (audio_extn_passthru_is_enabled()) {
4588 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304589 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304590
4591 if((out->format == AUDIO_FORMAT_DTS) ||
4592 (out->format == AUDIO_FORMAT_DTS_HD)) {
4593 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4594 buffer, bytes);
4595 if (ret) {
4596 if (ret != -ENOSYS) {
4597 out->is_iec61937_info_available = false;
4598 ALOGD("iec61937 transmission info not yet updated retry");
4599 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304600 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304601 /* if stream has started and after that there is
4602 * stream config change (iec transmission config)
4603 * then trigger select_device to update backend configuration.
4604 */
4605 out->stream_config_changed = true;
4606 pthread_mutex_lock(&adev->lock);
4607 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304608 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4609 ret = -EINVAL;
4610 goto exit;
4611 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304612 pthread_mutex_unlock(&adev->lock);
4613 out->stream_config_changed = false;
4614 out->is_iec61937_info_available = true;
4615 }
4616 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304617
Garmond Leung317cbf12017-09-13 16:20:50 -07004618 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304619 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4620 (out->is_iec61937_info_available == true)) {
4621 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4622 ret = -EINVAL;
4623 goto exit;
4624 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304625 }
4626 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304627
4628 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4629 (audio_extn_a2dp_is_suspended())) {
4630 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4631 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304632 ret = -EIO;
4633 goto exit;
4634 }
4635 }
4636 }
4637
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004638 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004639 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004640 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004641 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4642 ret = voice_extn_compress_voip_start_output_stream(out);
4643 else
4644 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004645 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004646 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004648 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004649 goto exit;
4650 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304651 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004652 if (last_known_cal_step != -1) {
4653 ALOGD("%s: retry previous failed cal level set", __func__);
4654 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304655 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004656 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304657
4658 if ((out->is_iec61937_info_available == true) &&
4659 (audio_extn_passthru_is_passthrough_stream(out))&&
4660 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4661 ret = -EINVAL;
4662 goto exit;
4663 }
Surendar Karka5a18a7a2018-04-26 11:28:38 +05304664 if (out->set_dual_mono)
4665 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004666 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004667
Ashish Jain81eb2a82015-05-13 10:52:34 +05304668 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004669 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304670 adev->is_channel_status_set = true;
4671 }
4672
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004673 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004674 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004675 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004676 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004677 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4678 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304679 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4680 ALOGD("copl(%p):send next track params in gapless", out);
4681 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4682 out->send_next_track_params = false;
4683 out->is_compr_metadata_avail = false;
4684 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004685 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304686 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304687 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004688
Ashish Jain83a6cc22016-06-28 14:34:17 +05304689 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304690 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304691 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304692 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004693 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304694 return -EINVAL;
4695 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304696 audio_format_t dst_format = out->hal_op_format;
4697 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304698
4699 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4700 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4701
Ashish Jain83a6cc22016-06-28 14:34:17 +05304702 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304703 dst_format,
4704 buffer,
4705 src_format,
4706 frames);
4707
Ashish Jain83a6cc22016-06-28 14:34:17 +05304708 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304709 bytes_to_write);
4710
4711 /*Convert written bytes in audio flinger format*/
4712 if (ret > 0)
4713 ret = ((ret * format_to_bitwidth_table[out->format]) /
4714 format_to_bitwidth_table[dst_format]);
4715 }
4716 } else
4717 ret = compress_write(out->compr, buffer, bytes);
4718
Zhou Songc9672822017-08-16 16:01:39 +08004719 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4720 update_frames_written(out, bytes);
4721
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304722 if (ret < 0)
4723 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08004724 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304725 /*msg to cb thread only if non blocking write is enabled*/
4726 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304727 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004728 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304729 } else if (-ENETRESET == ret) {
4730 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304731 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304732 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304733 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004734 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304735 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004736 }
Ashish Jain5106d362016-05-11 19:23:33 +05304737
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304738 /* Call compr start only when non-zero bytes of data is there to be rendered */
4739 if (!out->playback_started && ret > 0) {
4740 int status = compress_start(out->compr);
4741 if (status < 0) {
4742 ret = status;
4743 ALOGE("%s: compr start failed with err %d", __func__, errno);
4744 goto exit;
4745 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004746 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004747 out->playback_started = 1;
4748 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004749
4750 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4751 popcount(out->channel_mask),
4752 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004753 }
4754 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004755 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004756 return ret;
4757 } else {
4758 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004759 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004760 if (out->muted)
4761 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004762 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
4763 __func__, frames, frame_size, bytes_to_write);
4764
Arun Mirpuridbef0c72018-09-12 18:36:10 -07004765 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4766 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004767 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4768 int16_t *src = (int16_t *)buffer;
4769 int16_t *dst = (int16_t *)buffer;
4770
4771 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
4772 out->format != AUDIO_FORMAT_PCM_16_BIT,
4773 "out_write called for incall music use case with wrong properties");
4774
4775 /*
4776 * FIXME: this can be removed once audio flinger mixer supports
4777 * mono output
4778 */
4779
4780 /*
4781 * Code below goes over each frame in the buffer and adds both
4782 * L and R samples and then divides by 2 to convert to mono
4783 */
4784 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
4785 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
4786 }
4787 bytes_to_write /= 2;
4788 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004789
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304790 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004791
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004792 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004793
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004794 if (out->config.rate)
4795 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4796 out->config.rate;
4797
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004798 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004799 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4800
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004801 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004802 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004803 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304804 out->convert_buffer != NULL) {
4805
4806 memcpy_by_audio_format(out->convert_buffer,
4807 out->hal_op_format,
4808 buffer,
4809 out->hal_ip_format,
4810 out->config.period_size * out->config.channels);
4811
4812 ret = pcm_write(out->pcm, out->convert_buffer,
4813 (out->config.period_size *
4814 out->config.channels *
4815 format_to_bitwidth_table[out->hal_op_format]));
4816 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304817 /*
4818 * To avoid underrun in DSP when the application is not pumping
4819 * data at required rate, check for the no. of bytes and ignore
4820 * pcm_write if it is less than actual buffer size.
4821 * It is a work around to a change in compress VOIP driver.
4822 */
4823 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4824 bytes < (out->config.period_size * out->config.channels *
4825 audio_bytes_per_sample(out->format))) {
4826 size_t voip_buf_size =
4827 out->config.period_size * out->config.channels *
4828 audio_bytes_per_sample(out->format);
4829 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4830 __func__, bytes, voip_buf_size);
4831 usleep(((uint64_t)voip_buf_size - bytes) *
4832 1000000 / audio_stream_out_frame_size(stream) /
4833 out_get_sample_rate(&out->stream.common));
4834 ret = 0;
4835 } else
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004836 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304837 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004838
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004839 release_out_focus(out);
4840
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304841 if (ret < 0)
4842 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004843 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304844 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004845 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004846 }
4847
4848exit:
Zhou Songc9672822017-08-16 16:01:39 +08004849 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304850 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304851 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304852 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004853 pthread_mutex_unlock(&out->lock);
4854
4855 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004856 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004857 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304858 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304859 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304860 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304861 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304862 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304863 out->standby = true;
4864 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304865 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304866 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4867 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4868 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004869
4870 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05304871 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004872 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004873 return ret;
4874 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004875 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004876 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004877 return bytes;
4878}
4879
4880static int out_get_render_position(const struct audio_stream_out *stream,
4881 uint32_t *dsp_frames)
4882{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004883 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004884
4885 if (dsp_frames == NULL)
4886 return -EINVAL;
4887
4888 *dsp_frames = 0;
4889 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004890 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304891
4892 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4893 * this operation and adev_close_output_stream(where out gets reset).
4894 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304895 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004896 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05304897 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004898 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304899 return 0;
4900 }
4901
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004902 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304903 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304904 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004905 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304906 if (ret < 0)
4907 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004908 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304909 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004910 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304911 if (-ENETRESET == ret) {
4912 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304913 out->card_status = CARD_STATUS_OFFLINE;
4914 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304915 } else if(ret < 0) {
4916 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304917 ret = -EINVAL;
4918 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304919 /*
4920 * Handle corner case where compress session is closed during SSR
4921 * and timestamp is queried
4922 */
4923 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304924 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304925 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304926 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004927 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05304928 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304929 pthread_mutex_unlock(&out->lock);
4930 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004931 } else if (audio_is_linear_pcm(out->format)) {
4932 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004933 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08004934 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004935 } else
4936 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004937}
4938
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004939static int out_add_audio_effect(const struct audio_stream *stream __unused,
4940 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004941{
4942 return 0;
4943}
4944
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004945static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4946 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004947{
4948 return 0;
4949}
4950
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004951static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4952 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004953{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304954 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004955}
4956
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004957static int out_get_presentation_position(const struct audio_stream_out *stream,
4958 uint64_t *frames, struct timespec *timestamp)
4959{
4960 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05304961 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07004962 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004963
Ashish Jain5106d362016-05-11 19:23:33 +05304964 /* below piece of code is not guarded against any lock because audioFliner serializes
4965 * this operation and adev_close_output_stream( where out gets reset).
4966 */
4967 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304968 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004969 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05304970 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4971 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4972 return 0;
4973 }
4974
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004975 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004976
Ashish Jain5106d362016-05-11 19:23:33 +05304977 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4978 ret = compress_get_tstamp(out->compr, &dsp_frames,
4979 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004980 // Adjustment accounts for A2dp encoder latency with offload usecases
4981 // Note: Encoder latency is returned in ms.
4982 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4983 unsigned long offset =
4984 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4985 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4986 }
Ashish Jain5106d362016-05-11 19:23:33 +05304987 ALOGVV("%s rendered frames %ld sample_rate %d",
4988 __func__, dsp_frames, out->sample_rate);
4989 *frames = dsp_frames;
4990 if (ret < 0)
4991 ret = -errno;
4992 if (-ENETRESET == ret) {
4993 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304994 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304995 ret = -EINVAL;
4996 } else
4997 ret = 0;
4998 /* this is the best we can do */
4999 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005000 } else {
5001 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005002 unsigned int avail;
5003 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5004 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5005 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5006 // This adjustment accounts for buffering after app processor.
5007 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005008 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005009 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005010
Weiyin Jiangd4633762018-03-16 12:05:03 +08005011 // Adjustment accounts for A2dp encoder latency with non offload usecases
5012 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5013 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5014 signed_frames -=
5015 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5016 }
5017
5018 // It would be unusual for this value to be negative, but check just in case ...
5019 if (signed_frames >= 0) {
5020 *frames = signed_frames;
5021 ret = 0;
5022 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005023 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305024 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305025 *frames = out->written;
5026 clock_gettime(CLOCK_MONOTONIC, timestamp);
5027 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005028 }
5029 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005030 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005031 return ret;
5032}
5033
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005034static int out_set_callback(struct audio_stream_out *stream,
5035 stream_callback_t callback, void *cookie)
5036{
5037 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005038 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005039
5040 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005041 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005042 out->client_callback = callback;
5043 out->client_cookie = cookie;
5044 if (out->adsp_hdlr_stream_handle) {
5045 ret = audio_extn_adsp_hdlr_stream_set_callback(
5046 out->adsp_hdlr_stream_handle,
5047 callback,
5048 cookie);
5049 if (ret)
5050 ALOGW("%s:adsp hdlr callback registration failed %d",
5051 __func__, ret);
5052 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005053 pthread_mutex_unlock(&out->lock);
5054 return 0;
5055}
5056
5057static int out_pause(struct audio_stream_out* stream)
5058{
5059 struct stream_out *out = (struct stream_out *)stream;
5060 int status = -ENOSYS;
5061 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005062 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005063 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005064 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005065 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305066 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305067 status = compress_pause(out->compr);
5068
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005069 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005070
Mingming Yin21854652016-04-13 11:54:02 -07005071 if (audio_extn_passthru_is_active()) {
5072 ALOGV("offload use case, pause passthru");
5073 audio_extn_passthru_on_pause(out);
5074 }
5075
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305076 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005077 audio_extn_dts_notify_playback_state(out->usecase, 0,
5078 out->sample_rate, popcount(out->channel_mask),
5079 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005080 }
5081 pthread_mutex_unlock(&out->lock);
5082 }
5083 return status;
5084}
5085
5086static int out_resume(struct audio_stream_out* stream)
5087{
5088 struct stream_out *out = (struct stream_out *)stream;
5089 int status = -ENOSYS;
5090 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005091 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005092 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005093 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005094 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005095 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305096 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305097 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005098 }
5099 if (!status) {
5100 out->offload_state = OFFLOAD_STATE_PLAYING;
5101 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305102 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005103 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5104 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005105 }
5106 pthread_mutex_unlock(&out->lock);
5107 }
5108 return status;
5109}
5110
5111static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5112{
5113 struct stream_out *out = (struct stream_out *)stream;
5114 int status = -ENOSYS;
5115 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005116 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005117 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005118 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5119 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5120 else
5121 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5122 pthread_mutex_unlock(&out->lock);
5123 }
5124 return status;
5125}
5126
5127static int out_flush(struct audio_stream_out* stream)
5128{
5129 struct stream_out *out = (struct stream_out *)stream;
5130 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005131 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005132 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005133 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005134 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5135 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005136 } else {
5137 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5138 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005139 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005140 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005141 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005142 return 0;
5143 }
5144 return -ENOSYS;
5145}
5146
Haynes Mathew George16081042017-05-31 17:16:49 -07005147static int out_stop(const struct audio_stream_out* stream)
5148{
5149 struct stream_out *out = (struct stream_out *)stream;
5150 struct audio_device *adev = out->dev;
5151 int ret = -ENOSYS;
5152
5153 ALOGV("%s", __func__);
5154 pthread_mutex_lock(&adev->lock);
5155 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5156 out->playback_started && out->pcm != NULL) {
5157 pcm_stop(out->pcm);
5158 ret = stop_output_stream(out);
5159 out->playback_started = false;
5160 }
5161 pthread_mutex_unlock(&adev->lock);
5162 return ret;
5163}
5164
5165static int out_start(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 ret = start_output_stream(out);
5176 if (ret == 0) {
5177 out->playback_started = true;
5178 }
5179 }
5180 pthread_mutex_unlock(&adev->lock);
5181 return ret;
5182}
5183
5184/*
5185 * Modify config->period_count based on min_size_frames
5186 */
5187static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5188{
5189 int periodCountRequested = (min_size_frames + config->period_size - 1)
5190 / config->period_size;
5191 int periodCount = MMAP_PERIOD_COUNT_MIN;
5192
5193 ALOGV("%s original config.period_size = %d config.period_count = %d",
5194 __func__, config->period_size, config->period_count);
5195
5196 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5197 periodCount *= 2;
5198 }
5199 config->period_count = periodCount;
5200
5201 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5202}
5203
5204static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5205 int32_t min_size_frames,
5206 struct audio_mmap_buffer_info *info)
5207{
5208 struct stream_out *out = (struct stream_out *)stream;
5209 struct audio_device *adev = out->dev;
5210 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005211 unsigned int offset1 = 0;
5212 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005213 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005214 uint32_t mmap_size;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005215 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005216
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005217 ALOGD("%s", __func__);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305218 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005219 pthread_mutex_lock(&adev->lock);
5220
Sharad Sangle90e613f2018-05-04 16:15:38 +05305221 if (CARD_STATUS_OFFLINE == out->card_status ||
5222 CARD_STATUS_OFFLINE == adev->card_status) {
5223 ALOGW("out->card_status or adev->card_status offline, try again");
5224 ret = -EIO;
5225 goto exit;
5226 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005227 if (info == NULL || min_size_frames == 0) {
5228 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5229 ret = -EINVAL;
5230 goto exit;
5231 }
5232 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5233 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5234 ret = -ENOSYS;
5235 goto exit;
5236 }
5237 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5238 if (out->pcm_device_id < 0) {
5239 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5240 __func__, out->pcm_device_id, out->usecase);
5241 ret = -EINVAL;
5242 goto exit;
5243 }
5244
5245 adjust_mmap_period_count(&out->config, min_size_frames);
5246
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005247 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005248 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5249 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5250 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305251 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
5252 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5253 out->card_status = CARD_STATUS_OFFLINE;
5254 adev->card_status = CARD_STATUS_OFFLINE;
5255 ret = -EIO;
5256 goto exit;
5257 }
5258
Haynes Mathew George16081042017-05-31 17:16:49 -07005259 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5260 step = "open";
5261 ret = -ENODEV;
5262 goto exit;
5263 }
5264 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5265 if (ret < 0) {
5266 step = "begin";
5267 goto exit;
5268 }
5269 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005270 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005271 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005272 ret = platform_get_mmap_data_fd(adev->platform,
5273 out->pcm_device_id, 0 /*playback*/,
5274 &info->shared_memory_fd,
5275 &mmap_size);
5276 if (ret < 0) {
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005277 // Fall back to non exclusive mode
5278 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5279 } else {
5280 if (mmap_size < buffer_size) {
5281 step = "mmap";
5282 goto exit;
5283 }
5284 // FIXME: indicate exclusive mode support by returning a negative buffer size
5285 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005286 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005287 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07005288
5289 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5290 if (ret < 0) {
5291 step = "commit";
5292 goto exit;
5293 }
5294
5295 out->standby = false;
5296 ret = 0;
5297
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005298 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005299 __func__, info->shared_memory_address, info->buffer_size_frames);
5300
5301exit:
5302 if (ret != 0) {
5303 if (out->pcm == NULL) {
5304 ALOGE("%s: %s - %d", __func__, step, ret);
5305 } else {
5306 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5307 pcm_close(out->pcm);
5308 out->pcm = NULL;
5309 }
5310 }
5311 pthread_mutex_unlock(&adev->lock);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305312 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005313 return ret;
5314}
5315
5316static int out_get_mmap_position(const struct audio_stream_out *stream,
5317 struct audio_mmap_position *position)
5318{
5319 struct stream_out *out = (struct stream_out *)stream;
5320 ALOGVV("%s", __func__);
5321 if (position == NULL) {
5322 return -EINVAL;
5323 }
5324 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005325 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005326 return -ENOSYS;
5327 }
5328 if (out->pcm == NULL) {
5329 return -ENOSYS;
5330 }
5331
5332 struct timespec ts = { 0, 0 };
5333 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5334 if (ret < 0) {
5335 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5336 return ret;
5337 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005338 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005339 return 0;
5340}
5341
5342
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005343/** audio_stream_in implementation **/
5344static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5345{
5346 struct stream_in *in = (struct stream_in *)stream;
5347
5348 return in->config.rate;
5349}
5350
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005351static int in_set_sample_rate(struct audio_stream *stream __unused,
5352 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005353{
5354 return -ENOSYS;
5355}
5356
5357static size_t in_get_buffer_size(const struct audio_stream *stream)
5358{
5359 struct stream_in *in = (struct stream_in *)stream;
5360
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005361 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5362 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005363 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5364 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 -07005365 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5366 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305367 else if(audio_extn_cin_attached_usecase(in->usecase))
5368 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005369
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005370 return in->config.period_size * in->af_period_multiplier *
5371 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005372}
5373
5374static uint32_t in_get_channels(const struct audio_stream *stream)
5375{
5376 struct stream_in *in = (struct stream_in *)stream;
5377
5378 return in->channel_mask;
5379}
5380
5381static audio_format_t in_get_format(const struct audio_stream *stream)
5382{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005383 struct stream_in *in = (struct stream_in *)stream;
5384
5385 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005386}
5387
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005388static int in_set_format(struct audio_stream *stream __unused,
5389 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005390{
5391 return -ENOSYS;
5392}
5393
5394static int in_standby(struct audio_stream *stream)
5395{
5396 struct stream_in *in = (struct stream_in *)stream;
5397 struct audio_device *adev = in->dev;
5398 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305399 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5400 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005401 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305402
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005403 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005404 if (!in->standby && in->is_st_session) {
5405 ALOGD("%s: sound trigger pcm stop lab", __func__);
5406 audio_extn_sound_trigger_stop_lab(in);
5407 in->standby = 1;
5408 }
5409
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005410 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005411 if (adev->adm_deregister_stream)
5412 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5413
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005414 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005415 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005416 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005417 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005418 voice_extn_compress_voip_close_input_stream(stream);
5419 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005420 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5421 do_stop = in->capture_started;
5422 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005423 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305424 if (audio_extn_cin_attached_usecase(in->usecase))
5425 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005426 }
5427
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005428 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005429 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005430 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005431 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005432 in->pcm = NULL;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005433 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005434
5435 if (do_stop)
5436 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005437 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005438 }
5439 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005440 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005441 return status;
5442}
5443
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005444static int in_dump(const struct audio_stream *stream __unused,
5445 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005446{
5447 return 0;
5448}
5449
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305450static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5451{
5452 if (!stream || !parms)
5453 return;
5454
5455 struct stream_in *in = (struct stream_in *)stream;
5456 struct audio_device *adev = in->dev;
5457
5458 card_status_t status;
5459 int card;
5460 if (parse_snd_card_status(parms, &card, &status) < 0)
5461 return;
5462
5463 pthread_mutex_lock(&adev->lock);
5464 bool valid_cb = (card == adev->snd_card);
5465 pthread_mutex_unlock(&adev->lock);
5466
5467 if (!valid_cb)
5468 return;
5469
5470 lock_input_stream(in);
5471 if (in->card_status != status)
5472 in->card_status = status;
5473 pthread_mutex_unlock(&in->lock);
5474
5475 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5476 use_case_table[in->usecase],
5477 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5478
5479 // a better solution would be to report error back to AF and let
5480 // it put the stream to standby
5481 if (status == CARD_STATUS_OFFLINE)
5482 in_standby(&in->stream.common);
5483
5484 return;
5485}
5486
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005487static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5488{
5489 struct stream_in *in = (struct stream_in *)stream;
5490 struct audio_device *adev = in->dev;
5491 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005492 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005493 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005494
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305495 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005496 parms = str_parms_create_str(kvpairs);
5497
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305498 if (!parms)
5499 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005500 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005501 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005502
5503 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5504 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005505 val = atoi(value);
5506 /* no audio source uses val == 0 */
5507 if ((in->source != val) && (val != 0)) {
5508 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005509 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5510 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5511 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005512 (in->config.rate == 8000 || in->config.rate == 16000 ||
5513 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005514 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005515 err = voice_extn_compress_voip_open_input_stream(in);
5516 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005517 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005518 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005519 }
5520 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005521 }
5522 }
5523
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005524 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5525 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005526 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005527 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5528
5529 // Workaround: If routing to an non existing usb device, fail gracefully
5530 // The routing request will otherwise block during 10 second
5531 int card;
5532 if (audio_is_usb_in_device(val) &&
5533 (card = get_alive_usb_card(parms)) >= 0) {
5534
5535 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5536 ret = -ENOSYS;
5537 } else {
5538
5539 in->device = val;
5540 /* If recording is in progress, change the tx device to new device */
5541 if (!in->standby && !in->is_st_session) {
5542 ALOGV("update input routing change");
5543 // inform adm before actual routing to prevent glitches.
5544 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005545 adev->adm_on_routing_change(adev->adm_data,
5546 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005547 ret = select_devices(adev, in->usecase);
5548 }
5549 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005550 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005551 }
5552 }
5553
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305554 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5555 if (err >= 0) {
5556 strlcpy(in->profile, value, sizeof(in->profile));
5557 ALOGV("updating stream profile with value '%s'", in->profile);
5558 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5559 &adev->streams_input_cfg_list,
5560 in->device, in->flags, in->format,
5561 in->sample_rate, in->bit_width,
5562 in->profile, &in->app_type_cfg);
5563 }
5564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005565 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005566 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005567
5568 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305569error:
Eric Laurent994a6932013-07-17 11:51:42 -07005570 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005571 return ret;
5572}
5573
5574static char* in_get_parameters(const struct audio_stream *stream,
5575 const char *keys)
5576{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005577 struct stream_in *in = (struct stream_in *)stream;
5578 struct str_parms *query = str_parms_create_str(keys);
5579 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005580 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005581
5582 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005583 if (reply) {
5584 str_parms_destroy(reply);
5585 }
5586 if (query) {
5587 str_parms_destroy(query);
5588 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005589 ALOGE("in_get_parameters: failed to create query or reply");
5590 return NULL;
5591 }
5592
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005593 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005594
5595 voice_extn_in_get_parameters(in, query, reply);
5596
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005597 stream_get_parameter_channels(query, reply,
5598 &in->supported_channel_masks[0]);
5599 stream_get_parameter_formats(query, reply,
5600 &in->supported_formats[0]);
5601 stream_get_parameter_rates(query, reply,
5602 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005603 str = str_parms_to_str(reply);
5604 str_parms_destroy(query);
5605 str_parms_destroy(reply);
5606
5607 ALOGV("%s: exit: returns - %s", __func__, str);
5608 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005609}
5610
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005611static int in_set_gain(struct audio_stream_in *stream __unused,
5612 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005613{
5614 return 0;
5615}
5616
5617static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5618 size_t bytes)
5619{
5620 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305621
5622 if (in == NULL) {
5623 ALOGE("%s: stream_in ptr is NULL", __func__);
5624 return -EINVAL;
5625 }
5626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005627 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305628 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305629 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005630
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005631 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305632
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005633 if (in->is_st_session) {
5634 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5635 /* Read from sound trigger HAL */
5636 audio_extn_sound_trigger_read(in, buffer, bytes);
5637 pthread_mutex_unlock(&in->lock);
5638 return bytes;
5639 }
5640
Haynes Mathew George16081042017-05-31 17:16:49 -07005641 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5642 ret = -ENOSYS;
5643 goto exit;
5644 }
5645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005646 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005647 pthread_mutex_lock(&adev->lock);
5648 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5649 ret = voice_extn_compress_voip_start_input_stream(in);
5650 else
5651 ret = start_input_stream(in);
5652 pthread_mutex_unlock(&adev->lock);
5653 if (ret != 0) {
5654 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005655 }
5656 in->standby = 0;
5657 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005658
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005659 // what's the duration requested by the client?
5660 long ns = 0;
5661
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305662 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005663 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5664 in->config.rate;
5665
5666 request_in_focus(in, ns);
5667 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005668
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305669 if (audio_extn_cin_attached_usecase(in->usecase)) {
5670 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5671 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305672 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005673 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305674 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005675 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005676 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005677 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005678 } else if (audio_extn_ffv_get_stream() == in) {
5679 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305680 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005681 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305682 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5683 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5684 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5685 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305686 ret = -EINVAL;
5687 goto exit;
5688 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305689 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305690 ret = -errno;
5691 }
5692 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305693 /* bytes read is always set to bytes for non compress usecases */
5694 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005695 }
5696
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005697 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005699 /*
5700 * Instead of writing zeroes here, we could trust the hardware
5701 * to always provide zeroes when muted.
5702 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305703 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5704 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005705 memset(buffer, 0, bytes);
5706
5707exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005708 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305709 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005710 pthread_mutex_unlock(&in->lock);
5711
5712 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305713 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305714 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305715 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305716 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305717 in->standby = true;
5718 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305719 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5720 bytes_read = bytes;
5721 memset(buffer, 0, bytes);
5722 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005723 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005724 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305725 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305726 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005727 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305728 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005729}
5730
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005731static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005732{
5733 return 0;
5734}
5735
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005736static int add_remove_audio_effect(const struct audio_stream *stream,
5737 effect_handle_t effect,
5738 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005739{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005740 struct stream_in *in = (struct stream_in *)stream;
5741 int status = 0;
5742 effect_descriptor_t desc;
5743
5744 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005745 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5746
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005747 if (status != 0)
5748 return status;
5749
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005750 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005751 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08005752 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5753 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005754 in->enable_aec != enable &&
5755 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5756 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005757 if (!in->standby) {
5758 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5759 select_devices(in->dev, in->usecase);
5760 }
5761
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005762 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005763 if (in->enable_ns != enable &&
5764 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5765 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005766 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08005767 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5768 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005769 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5770 select_devices(in->dev, in->usecase);
5771 } else
5772 select_devices(in->dev, in->usecase);
5773 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005774 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005775 pthread_mutex_unlock(&in->dev->lock);
5776 pthread_mutex_unlock(&in->lock);
5777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005778 return 0;
5779}
5780
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005781static int in_add_audio_effect(const struct audio_stream *stream,
5782 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005783{
Eric Laurent994a6932013-07-17 11:51:42 -07005784 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005785 return add_remove_audio_effect(stream, effect, true);
5786}
5787
5788static int in_remove_audio_effect(const struct audio_stream *stream,
5789 effect_handle_t effect)
5790{
Eric Laurent994a6932013-07-17 11:51:42 -07005791 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005792 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005793}
5794
Haynes Mathew George16081042017-05-31 17:16:49 -07005795static int in_stop(const struct audio_stream_in* stream)
5796{
5797 struct stream_in *in = (struct stream_in *)stream;
5798 struct audio_device *adev = in->dev;
5799
5800 int ret = -ENOSYS;
5801 ALOGV("%s", __func__);
5802 pthread_mutex_lock(&adev->lock);
5803 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5804 in->capture_started && in->pcm != NULL) {
5805 pcm_stop(in->pcm);
5806 ret = stop_input_stream(in);
5807 in->capture_started = false;
5808 }
5809 pthread_mutex_unlock(&adev->lock);
5810 return ret;
5811}
5812
5813static int in_start(const struct audio_stream_in* stream)
5814{
5815 struct stream_in *in = (struct stream_in *)stream;
5816 struct audio_device *adev = in->dev;
5817 int ret = -ENOSYS;
5818
5819 ALOGV("%s in %p", __func__, in);
5820 pthread_mutex_lock(&adev->lock);
5821 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5822 !in->capture_started && in->pcm != NULL) {
5823 if (!in->capture_started) {
5824 ret = start_input_stream(in);
5825 if (ret == 0) {
5826 in->capture_started = true;
5827 }
5828 }
5829 }
5830 pthread_mutex_unlock(&adev->lock);
5831 return ret;
5832}
5833
5834static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5835 int32_t min_size_frames,
5836 struct audio_mmap_buffer_info *info)
5837{
5838 struct stream_in *in = (struct stream_in *)stream;
5839 struct audio_device *adev = in->dev;
5840 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005841 unsigned int offset1 = 0;
5842 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005843 const char *step = "";
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005844 uint32_t mmap_size = 0;
5845 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005846
5847 pthread_mutex_lock(&adev->lock);
5848 ALOGV("%s in %p", __func__, in);
5849
Sharad Sangle90e613f2018-05-04 16:15:38 +05305850 if (CARD_STATUS_OFFLINE == in->card_status||
5851 CARD_STATUS_OFFLINE == adev->card_status) {
5852 ALOGW("in->card_status or adev->card_status offline, try again");
5853 ret = -EIO;
5854 goto exit;
5855 }
5856
Haynes Mathew George16081042017-05-31 17:16:49 -07005857 if (info == NULL || min_size_frames == 0) {
5858 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5859 ret = -EINVAL;
5860 goto exit;
5861 }
5862 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5863 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5864 ALOGV("%s in %p", __func__, in);
5865 ret = -ENOSYS;
5866 goto exit;
5867 }
5868 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5869 if (in->pcm_device_id < 0) {
5870 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5871 __func__, in->pcm_device_id, in->usecase);
5872 ret = -EINVAL;
5873 goto exit;
5874 }
5875
5876 adjust_mmap_period_count(&in->config, min_size_frames);
5877
5878 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5879 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5880 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5881 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305882 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
5883 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5884 in->card_status = CARD_STATUS_OFFLINE;
5885 adev->card_status = CARD_STATUS_OFFLINE;
5886 ret = -EIO;
5887 goto exit;
5888 }
5889
Haynes Mathew George16081042017-05-31 17:16:49 -07005890 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5891 step = "open";
5892 ret = -ENODEV;
5893 goto exit;
5894 }
5895
5896 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5897 if (ret < 0) {
5898 step = "begin";
5899 goto exit;
5900 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005901
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005902 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5903 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
5904 info->burst_size_frames = in->config.period_size;
5905 ret = platform_get_mmap_data_fd(adev->platform,
5906 in->pcm_device_id, 1 /*capture*/,
5907 &info->shared_memory_fd,
5908 &mmap_size);
5909 if (ret < 0) {
5910 // Fall back to non exclusive mode
5911 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
5912 } else {
5913 if (mmap_size < buffer_size) {
5914 step = "mmap";
5915 goto exit;
5916 }
5917 // FIXME: indicate exclusive mode support by returning a negative buffer size
5918 info->buffer_size_frames *= -1;
5919 }
5920
5921 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07005922
5923 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
5924 if (ret < 0) {
5925 step = "commit";
5926 goto exit;
5927 }
5928
5929 in->standby = false;
5930 ret = 0;
5931
5932 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5933 __func__, info->shared_memory_address, info->buffer_size_frames);
5934
5935exit:
5936 if (ret != 0) {
5937 if (in->pcm == NULL) {
5938 ALOGE("%s: %s - %d", __func__, step, ret);
5939 } else {
5940 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
5941 pcm_close(in->pcm);
5942 in->pcm = NULL;
5943 }
5944 }
5945 pthread_mutex_unlock(&adev->lock);
5946 return ret;
5947}
5948
5949static int in_get_mmap_position(const struct audio_stream_in *stream,
5950 struct audio_mmap_position *position)
5951{
5952 struct stream_in *in = (struct stream_in *)stream;
5953 ALOGVV("%s", __func__);
5954 if (position == NULL) {
5955 return -EINVAL;
5956 }
5957 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
5958 return -ENOSYS;
5959 }
5960 if (in->pcm == NULL) {
5961 return -ENOSYS;
5962 }
5963 struct timespec ts = { 0, 0 };
5964 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
5965 if (ret < 0) {
5966 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
5967 return ret;
5968 }
Naresh Tannirua15d7e92018-11-02 09:49:44 +05305969 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005970 return 0;
5971}
5972
Naresh Tannirudcb47c52018-06-25 16:23:32 +05305973static int in_get_active_microphones(const struct audio_stream_in *stream,
5974 struct audio_microphone_characteristic_t *mic_array,
5975 size_t *mic_count) {
5976 struct stream_in *in = (struct stream_in *)stream;
5977 struct audio_device *adev = in->dev;
5978 ALOGVV("%s", __func__);
5979
5980 lock_input_stream(in);
5981 pthread_mutex_lock(&adev->lock);
5982 int ret = platform_get_active_microphones(adev->platform,
5983 audio_channel_count_from_in_mask(in->channel_mask),
5984 in->usecase, mic_array, mic_count);
5985 pthread_mutex_unlock(&adev->lock);
5986 pthread_mutex_unlock(&in->lock);
5987
5988 return ret;
5989}
5990
5991static int adev_get_microphones(const struct audio_hw_device *dev,
5992 struct audio_microphone_characteristic_t *mic_array,
5993 size_t *mic_count) {
5994 struct audio_device *adev = (struct audio_device *)dev;
5995 ALOGVV("%s", __func__);
5996
5997 pthread_mutex_lock(&adev->lock);
5998 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
5999 pthread_mutex_unlock(&adev->lock);
6000
6001 return ret;
6002}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306003int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006004 audio_io_handle_t handle,
6005 audio_devices_t devices,
6006 audio_output_flags_t flags,
6007 struct audio_config *config,
6008 struct audio_stream_out **stream_out,
6009 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006010{
6011 struct audio_device *adev = (struct audio_device *)dev;
6012 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306013 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006014 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006015 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306016 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006017 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6018 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6019 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6020 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006021
kunleizdff872d2018-08-20 14:40:33 +08006022 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006023 is_usb_dev = false;
6024 devices = AUDIO_DEVICE_OUT_SPEAKER;
6025 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6026 __func__, devices);
6027 }
6028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006029 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306030
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006031 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6032
Mingming Yin3a941d42016-02-17 18:08:05 -08006033 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6034 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306035 devices, flags, &out->stream);
6036
6037
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006038 if (!out) {
6039 return -ENOMEM;
6040 }
6041
Haynes Mathew George204045b2015-02-25 20:32:03 -08006042 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006043 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306044 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006045 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006046 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6047
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006048 if (devices == AUDIO_DEVICE_NONE)
6049 devices = AUDIO_DEVICE_OUT_SPEAKER;
6050
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006051 out->flags = flags;
6052 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006053 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006054 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006055 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306056 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306057 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6058 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6059 else
6060 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006061 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006062 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006063 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306064 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306065 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306066 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006067 out->hal_output_suspend_supported = 0;
6068 out->dynamic_pm_qos_config_supported = 0;
Surendar Karka5a18a7a2018-04-26 11:28:38 +05306069 out->set_dual_mono = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006070
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306071 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306072 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006073 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6074
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006075 if (audio_is_linear_pcm(out->format) &&
6076 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
6077 pthread_mutex_lock(&adev->lock);
6078 if (is_hdmi) {
6079 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6080 ret = read_hdmi_sink_caps(out);
6081 } else if (is_usb_dev) {
6082 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6083 &config->format,
6084 &out->supported_formats[0],
6085 MAX_SUPPORTED_FORMATS,
6086 &config->channel_mask,
6087 &out->supported_channel_masks[0],
6088 MAX_SUPPORTED_CHANNEL_MASKS,
6089 &config->sample_rate,
6090 &out->supported_sample_rates[0],
6091 MAX_SUPPORTED_SAMPLE_RATES);
6092 ALOGV("plugged dev USB ret %d", ret);
6093 } else {
6094 ret = -1;
6095 }
6096 pthread_mutex_unlock(&adev->lock);
6097 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006098 if (ret == -ENOSYS) {
6099 /* ignore and go with default */
6100 ret = 0;
6101 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006102 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006103 goto error_open;
6104 }
6105 }
6106 }
6107
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006108 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07006109#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006110 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6111 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6112 out->sample_rate == 32000 || out->sample_rate == 48000)) {
6113 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
6114 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
6115 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
6116
6117 out->config = default_pcm_config_voip_copp;
6118 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6119 out->config.rate = out->sample_rate;
6120
6121#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05306122 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006123 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08006124 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006125 ret = voice_extn_compress_voip_open_output_stream(out);
6126 if (ret != 0) {
6127 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6128 __func__, ret);
6129 goto error_open;
6130 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006131#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006132 } else if (audio_is_linear_pcm(out->format) &&
6133 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6134 out->channel_mask = config->channel_mask;
6135 out->sample_rate = config->sample_rate;
6136 out->format = config->format;
6137 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6138 // does this change?
6139 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6140 out->config.rate = config->sample_rate;
6141 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6142 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6143 audio_bytes_per_sample(config->format));
6144 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006145 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306146 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306147 pthread_mutex_lock(&adev->lock);
6148 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6149 pthread_mutex_unlock(&adev->lock);
6150
6151 // reject offload during card offline to allow
6152 // fallback to s/w paths
6153 if (offline) {
6154 ret = -ENODEV;
6155 goto error_open;
6156 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006157
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006158 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6159 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6160 ALOGE("%s: Unsupported Offload information", __func__);
6161 ret = -EINVAL;
6162 goto error_open;
6163 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006164
Atul Khare3fa6e542017-08-09 00:56:17 +05306165 if (config->offload_info.format == 0)
6166 config->offload_info.format = config->format;
6167 if (config->offload_info.sample_rate == 0)
6168 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006169
Mingming Yin90310102013-11-13 16:57:00 -08006170 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306171 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006172 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006173 ret = -EINVAL;
6174 goto error_open;
6175 }
6176
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006177 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6178 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6179 (audio_extn_passthru_is_passthrough_stream(out)) &&
6180 !((config->sample_rate == 48000) ||
6181 (config->sample_rate == 96000) ||
6182 (config->sample_rate == 192000))) {
6183 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6184 __func__, config->sample_rate, config->offload_info.format);
6185 ret = -EINVAL;
6186 goto error_open;
6187 }
6188
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006189 out->compr_config.codec = (struct snd_codec *)
6190 calloc(1, sizeof(struct snd_codec));
6191
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006192 if (!out->compr_config.codec) {
6193 ret = -ENOMEM;
6194 goto error_open;
6195 }
6196
Dhananjay Kumarac341582017-02-23 23:42:25 +05306197 out->stream.pause = out_pause;
6198 out->stream.resume = out_resume;
6199 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306200 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306201 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006202 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306203 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006204 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306205 } else {
6206 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6207 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006208 }
vivek mehta446c3962015-09-14 10:57:35 -07006209
6210 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006211 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6212 config->format == 0 && config->sample_rate == 0 &&
6213 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006214 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006215 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6216 } else {
6217 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6218 ret = -EEXIST;
6219 goto error_open;
6220 }
vivek mehta446c3962015-09-14 10:57:35 -07006221 }
6222
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006223 if (config->offload_info.channel_mask)
6224 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006225 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006226 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006227 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006228 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306229 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006230 ret = -EINVAL;
6231 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006232 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006233
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006234 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006235 out->sample_rate = config->offload_info.sample_rate;
6236
Mingming Yin3ee55c62014-08-04 14:23:35 -07006237 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006238
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306239 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306240 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306241 audio_extn_dolby_send_ddp_endp_params(adev);
6242 audio_extn_dolby_set_dmid(adev);
6243 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006244
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006245 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006246 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006247 out->compr_config.codec->bit_rate =
6248 config->offload_info.bit_rate;
6249 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306250 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006251 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306252 /* Update bit width only for non passthrough usecases.
6253 * For passthrough usecases, the output will always be opened @16 bit
6254 */
6255 if (!audio_extn_passthru_is_passthrough_stream(out))
6256 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306257
6258 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6259 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6260 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6261
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006262 /*TODO: Do we need to change it for passthrough */
6263 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006264
Manish Dewangana6fc5442015-08-24 20:30:31 +05306265 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6266 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306267 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306268 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306269 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6270 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306271
6272 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6273 AUDIO_FORMAT_PCM) {
6274
6275 /*Based on platform support, configure appropriate alsa format for corresponding
6276 *hal input format.
6277 */
6278 out->compr_config.codec->format = hal_format_to_alsa(
6279 config->offload_info.format);
6280
Ashish Jain83a6cc22016-06-28 14:34:17 +05306281 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306282 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306283 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306284
Dhananjay Kumarac341582017-02-23 23:42:25 +05306285 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306286 *hal input format and alsa format might differ based on platform support.
6287 */
6288 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306289 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306290
6291 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6292
6293 /* Check if alsa session is configured with the same format as HAL input format,
6294 * if not then derive correct fragment size needed to accomodate the
6295 * conversion of HAL input format to alsa format.
6296 */
6297 audio_extn_utils_update_direct_pcm_fragment_size(out);
6298
6299 /*if hal input and output fragment size is different this indicates HAL input format is
6300 *not same as the alsa format
6301 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306302 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306303 /*Allocate a buffer to convert input data to the alsa configured format.
6304 *size of convert buffer is equal to the size required to hold one fragment size
6305 *worth of pcm data, this is because flinger does not write more than fragment_size
6306 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306307 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6308 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306309 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6310 ret = -ENOMEM;
6311 goto error_open;
6312 }
6313 }
6314 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6315 out->compr_config.fragment_size =
6316 audio_extn_passthru_get_buffer_size(&config->offload_info);
6317 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6318 } else {
6319 out->compr_config.fragment_size =
6320 platform_get_compress_offload_buffer_size(&config->offload_info);
6321 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6322 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006323
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306324 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6325 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6326 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006327 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306328 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006329
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306330 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6331 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6332 }
6333
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006334 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6335 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006336
Manish Dewangan69426c82017-01-30 17:35:36 +05306337 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6338 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6339 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6340 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6341 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6342 } else {
6343 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6344 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006345
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306346 memset(&out->channel_map_param, 0,
6347 sizeof(struct audio_out_channel_map_param));
6348
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006349 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306350 out->send_next_track_params = false;
6351 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006352 out->offload_state = OFFLOAD_STATE_IDLE;
6353 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006354 out->writeAt.tv_sec = 0;
6355 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006356
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006357 audio_extn_dts_create_state_notifier_node(out->usecase);
6358
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006359 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6360 __func__, config->offload_info.version,
6361 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306362
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306363 /* Check if DSD audio format is supported in codec
6364 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306365 */
6366
6367 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306368 (!platform_check_codec_dsd_support(adev->platform) ||
6369 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306370 ret = -EINVAL;
6371 goto error_open;
6372 }
6373
Ashish Jain5106d362016-05-11 19:23:33 +05306374 /* Disable gapless if any of the following is true
6375 * passthrough playback
6376 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306377 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306378 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306379 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306380 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006381 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306382 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306383 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306384 check_and_set_gapless_mode(adev, false);
6385 } else
6386 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006387
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306388 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006389 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6390 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306391 if (config->format == AUDIO_FORMAT_DSD) {
6392 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6393 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6394 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006395
6396 create_offload_callback_thread(out);
6397
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006398 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006399 switch (config->sample_rate) {
6400 case 0:
6401 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6402 break;
6403 case 8000:
6404 case 16000:
6405 case 48000:
6406 out->sample_rate = config->sample_rate;
6407 break;
6408 default:
6409 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
6410 config->sample_rate);
6411 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6412 ret = -EINVAL;
6413 goto error_open;
6414 }
6415 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6416 switch (config->channel_mask) {
6417 case AUDIO_CHANNEL_NONE:
6418 case AUDIO_CHANNEL_OUT_STEREO:
6419 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6420 break;
6421 default:
6422 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
6423 config->channel_mask);
6424 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6425 ret = -EINVAL;
6426 goto error_open;
6427 }
6428 switch (config->format) {
6429 case AUDIO_FORMAT_DEFAULT:
6430 case AUDIO_FORMAT_PCM_16_BIT:
6431 out->format = AUDIO_FORMAT_PCM_16_BIT;
6432 break;
6433 default:
6434 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
6435 config->format);
6436 config->format = AUDIO_FORMAT_PCM_16_BIT;
6437 ret = -EINVAL;
6438 goto error_open;
6439 }
6440
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306441 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006442 if (ret != 0) {
6443 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006444 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006445 goto error_open;
6446 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006447 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006448 if (config->sample_rate == 0)
6449 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6450 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6451 config->sample_rate != 8000) {
6452 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6453 ret = -EINVAL;
6454 goto error_open;
6455 }
6456 out->sample_rate = config->sample_rate;
6457 out->config.rate = config->sample_rate;
6458 if (config->format == AUDIO_FORMAT_DEFAULT)
6459 config->format = AUDIO_FORMAT_PCM_16_BIT;
6460 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6461 config->format = AUDIO_FORMAT_PCM_16_BIT;
6462 ret = -EINVAL;
6463 goto error_open;
6464 }
6465 out->format = config->format;
6466 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
6467 out->config = pcm_config_afe_proxy_playback;
6468 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006469 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05306470 unsigned int channels = 0;
6471 /*Update config params to default if not set by the caller*/
6472 if (config->sample_rate == 0)
6473 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6474 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6475 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6476 if (config->format == AUDIO_FORMAT_DEFAULT)
6477 config->format = AUDIO_FORMAT_PCM_16_BIT;
6478
6479 channels = audio_channel_count_from_out_mask(out->channel_mask);
6480
Varun Balaraje49253e2017-07-06 19:48:56 +05306481 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6482 out->usecase = get_interactive_usecase(adev);
6483 out->config = pcm_config_low_latency;
6484 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306485 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006486 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6487 out->flags);
6488 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006489 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6490 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6491 out->config = pcm_config_mmap_playback;
6492 out->stream.start = out_start;
6493 out->stream.stop = out_stop;
6494 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6495 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306496 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6497 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006498 out->hal_output_suspend_supported =
6499 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6500 out->dynamic_pm_qos_config_supported =
6501 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6502 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006503 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6504 } else {
6505 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6506 //the mixer path will be a string similar to "low-latency-playback resume"
6507 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6508 strlcat(out->pm_qos_mixer_path,
6509 " resume", MAX_MIXER_PATH_LEN);
6510 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6511 out->pm_qos_mixer_path);
6512 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306513 out->config = pcm_config_low_latency;
6514 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6515 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6516 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306517 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6518 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6519 if (out->config.period_size <= 0) {
6520 ALOGE("Invalid configuration period size is not valid");
6521 ret = -EINVAL;
6522 goto error_open;
6523 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306524 } else {
6525 /* primary path is the default path selected if no other outputs are available/suitable */
6526 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6527 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6528 }
6529 out->hal_ip_format = format = out->format;
6530 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6531 out->hal_op_format = pcm_format_to_hal(out->config.format);
6532 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6533 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006534 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306535 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306536 if (out->hal_ip_format != out->hal_op_format) {
6537 uint32_t buffer_size = out->config.period_size *
6538 format_to_bitwidth_table[out->hal_op_format] *
6539 out->config.channels;
6540 out->convert_buffer = calloc(1, buffer_size);
6541 if (out->convert_buffer == NULL){
6542 ALOGE("Allocation failed for convert buffer for size %d",
6543 out->compr_config.fragment_size);
6544 ret = -ENOMEM;
6545 goto error_open;
6546 }
6547 ALOGD("Convert buffer allocated of size %d", buffer_size);
6548 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006549 }
6550
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006551 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6552 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306553
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006554 /* TODO remove this hardcoding and check why width is zero*/
6555 if (out->bit_width == 0)
6556 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306557 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006558 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006559 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306560 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306561 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006562 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6563 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6564 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006565 if(adev->primary_output == NULL)
6566 adev->primary_output = out;
6567 else {
6568 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006569 ret = -EEXIST;
6570 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006571 }
6572 }
6573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006574 /* Check if this usecase is already existing */
6575 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006576 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6577 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006578 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006579 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006580 ret = -EEXIST;
6581 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006582 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006583
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006584 pthread_mutex_unlock(&adev->lock);
6585
6586 out->stream.common.get_sample_rate = out_get_sample_rate;
6587 out->stream.common.set_sample_rate = out_set_sample_rate;
6588 out->stream.common.get_buffer_size = out_get_buffer_size;
6589 out->stream.common.get_channels = out_get_channels;
6590 out->stream.common.get_format = out_get_format;
6591 out->stream.common.set_format = out_set_format;
6592 out->stream.common.standby = out_standby;
6593 out->stream.common.dump = out_dump;
6594 out->stream.common.set_parameters = out_set_parameters;
6595 out->stream.common.get_parameters = out_get_parameters;
6596 out->stream.common.add_audio_effect = out_add_audio_effect;
6597 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6598 out->stream.get_latency = out_get_latency;
6599 out->stream.set_volume = out_set_volume;
6600 out->stream.write = out_write;
6601 out->stream.get_render_position = out_get_render_position;
6602 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006603 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006604
Haynes Mathew George16081042017-05-31 17:16:49 -07006605 if (out->realtime)
6606 out->af_period_multiplier = af_period_multiplier;
6607 else
6608 out->af_period_multiplier = 1;
6609
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006610 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006611 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006612 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006613
6614 config->format = out->stream.common.get_format(&out->stream.common);
6615 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6616 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05306617 register_format(out->format, out->supported_formats);
6618 register_channel_mask(out->channel_mask, out->supported_channel_masks);
6619 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006620
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306621 /*
6622 By locking output stream before registering, we allow the callback
6623 to update stream's state only after stream's initial state is set to
6624 adev state.
6625 */
6626 lock_output_stream(out);
6627 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6628 pthread_mutex_lock(&adev->lock);
6629 out->card_status = adev->card_status;
6630 pthread_mutex_unlock(&adev->lock);
6631 pthread_mutex_unlock(&out->lock);
6632
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006633 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306634 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006635 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006636
6637 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6638 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6639 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006640 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306641 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006642 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006643 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306644 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006645 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6646 out->usecase, PCM_PLAYBACK);
6647 hdlr_stream_cfg.flags = out->flags;
6648 hdlr_stream_cfg.type = PCM_PLAYBACK;
6649 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6650 &hdlr_stream_cfg);
6651 if (ret) {
6652 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6653 out->adsp_hdlr_stream_handle = NULL;
6654 }
6655 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306656 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006657 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006658 if (ret < 0) {
6659 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6660 out->ip_hdlr_handle = NULL;
6661 }
6662 }
Eric Laurent994a6932013-07-17 11:51:42 -07006663 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006664 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006665
6666error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306667 if (out->convert_buffer)
6668 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006669 free(out);
6670 *stream_out = NULL;
6671 ALOGD("%s: exit: ret %d", __func__, ret);
6672 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006673}
6674
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306675void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006676 struct audio_stream_out *stream)
6677{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006678 struct stream_out *out = (struct stream_out *)stream;
6679 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006680 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006681
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006682 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306683
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306684 // must deregister from sndmonitor first to prevent races
6685 // between the callback and close_stream
6686 audio_extn_snd_mon_unregister_listener(out);
6687
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006688 /* close adsp hdrl session before standby */
6689 if (out->adsp_hdlr_stream_handle) {
6690 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6691 if (ret)
6692 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6693 out->adsp_hdlr_stream_handle = NULL;
6694 }
6695
Manish Dewangan21a850a2017-08-14 12:03:55 +05306696 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006697 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6698 out->ip_hdlr_handle = NULL;
6699 }
6700
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006701 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306702 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006703 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306704 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306705 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006706 if(ret != 0)
6707 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6708 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006709 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006710 out_standby(&stream->common);
6711
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006712 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006713 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006714 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006715 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006716 if (out->compr_config.codec != NULL)
6717 free(out->compr_config.codec);
6718 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006719
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306720 out->a2dp_compress_mute = false;
6721
Varun Balaraje49253e2017-07-06 19:48:56 +05306722 if (is_interactive_usecase(out->usecase))
6723 free_interactive_usecase(adev, out->usecase);
6724
Ashish Jain83a6cc22016-06-28 14:34:17 +05306725 if (out->convert_buffer != NULL) {
6726 free(out->convert_buffer);
6727 out->convert_buffer = NULL;
6728 }
6729
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006730 if (adev->voice_tx_output == out)
6731 adev->voice_tx_output = NULL;
6732
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306733 if (adev->primary_output == out)
6734 adev->primary_output = NULL;
6735
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006736 pthread_cond_destroy(&out->cond);
6737 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006738 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006739 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006740}
6741
6742static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6743{
6744 struct audio_device *adev = (struct audio_device *)dev;
6745 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006746 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006747 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006748 int ret;
6749 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006750
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006751 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006752 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006753
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306754 if (!parms)
6755 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306756
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306757 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6758 if (ret >= 0) {
6759 /* When set to false, HAL should disable EC and NS */
6760 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6761 adev->bt_sco_on = true;
6762 else
6763 adev->bt_sco_on = false;
6764 }
6765
Naresh Tanniru4c630392014-05-12 01:05:52 +05306766 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006767 status = voice_set_parameters(adev, parms);
6768 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006769 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006770
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006771 status = platform_set_parameters(adev->platform, parms);
6772 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006773 goto done;
6774
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006775 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6776 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006777 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006778 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6779 adev->bluetooth_nrec = true;
6780 else
6781 adev->bluetooth_nrec = false;
6782 }
6783
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006784 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6785 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006786 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6787 adev->screen_off = false;
6788 else
6789 adev->screen_off = true;
6790 }
6791
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006792 ret = str_parms_get_int(parms, "rotation", &val);
6793 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006794 bool reverse_speakers = false;
6795 switch(val) {
6796 // FIXME: note that the code below assumes that the speakers are in the correct placement
6797 // relative to the user when the device is rotated 90deg from its default rotation. This
6798 // assumption is device-specific, not platform-specific like this code.
6799 case 270:
6800 reverse_speakers = true;
6801 break;
6802 case 0:
6803 case 90:
6804 case 180:
6805 break;
6806 default:
6807 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006808 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006809 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006810 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006811 // check and set swap
6812 // - check if orientation changed and speaker active
6813 // - set rotation and cache the rotation value
6814 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006815 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006816 }
6817
Mingming Yin514a8bc2014-07-29 15:22:21 -07006818 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6819 if (ret >= 0) {
6820 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6821 adev->bt_wb_speech_enabled = true;
6822 else
6823 adev->bt_wb_speech_enabled = false;
6824 }
6825
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006826 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6827 if (ret >= 0) {
6828 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306829 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08006830 if (audio_is_output_device(val) &&
6831 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006832 ALOGV("cache new ext disp type and edid");
6833 ret = platform_get_ext_disp_type(adev->platform);
6834 if (ret < 0) {
6835 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05306836 } else {
6837 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006838 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306839 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07006840 /*
6841 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6842 * Per AudioPolicyManager, USB device is higher priority than WFD.
6843 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6844 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6845 * starting voice call on USB
6846 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006847 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306848 if (ret >= 0)
6849 audio_extn_usb_add_device(device, atoi(value));
6850
Zhou Song6f862822017-11-06 17:27:57 +08006851 if (!audio_extn_usb_is_tunnel_supported()) {
6852 ALOGV("detected USB connect .. disable proxy");
6853 adev->allow_afe_proxy_usage = false;
6854 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006855 }
6856 }
6857
6858 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6859 if (ret >= 0) {
6860 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306861 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07006862 /*
6863 * The HDMI / Displayport disconnect handling has been moved to
6864 * audio extension to ensure that its parameters are not
6865 * invalidated prior to updating sysfs of the disconnect event
6866 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6867 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306868 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006869 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306870 if (ret >= 0)
6871 audio_extn_usb_remove_device(device, atoi(value));
6872
Zhou Song6f862822017-11-06 17:27:57 +08006873 if (!audio_extn_usb_is_tunnel_supported()) {
6874 ALOGV("detected USB disconnect .. enable proxy");
6875 adev->allow_afe_proxy_usage = true;
6876 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006877 }
6878 }
6879
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306880 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6881 if (ret >= 0) {
6882 struct audio_usecase *usecase;
6883 struct listnode *node;
6884 list_for_each(node, &adev->usecase_list) {
6885 usecase = node_to_item(node, struct audio_usecase, list);
6886 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07006887 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306888 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08006889
6890 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306891 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08006892 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306893 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306894 //force device switch to re configure encoder
6895 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306896 audio_extn_a2dp_set_handoff_mode(false);
6897 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306898 break;
6899 }
6900 }
6901 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006902
6903 //handle vr audio setparam
6904 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6905 value, sizeof(value));
6906 if (ret >= 0) {
6907 ALOGI("Setting vr mode to be %s", value);
6908 if (!strncmp(value, "true", 4)) {
6909 adev->vr_audio_mode_enabled = true;
6910 ALOGI("Setting vr mode to true");
6911 } else if (!strncmp(value, "false", 5)) {
6912 adev->vr_audio_mode_enabled = false;
6913 ALOGI("Setting vr mode to false");
6914 } else {
6915 ALOGI("wrong vr mode set");
6916 }
6917 }
6918
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306919 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006920done:
6921 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006922 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306923error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006924 ALOGV("%s: exit with code(%d)", __func__, status);
6925 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006926}
6927
6928static char* adev_get_parameters(const struct audio_hw_device *dev,
6929 const char *keys)
6930{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006931 struct audio_device *adev = (struct audio_device *)dev;
6932 struct str_parms *reply = str_parms_create();
6933 struct str_parms *query = str_parms_create_str(keys);
6934 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05306935 char value[256] = {0};
6936 int ret = 0;
6937
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006938 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006939 if (reply) {
6940 str_parms_destroy(reply);
6941 }
6942 if (query) {
6943 str_parms_destroy(query);
6944 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006945 ALOGE("adev_get_parameters: failed to create query or reply");
6946 return NULL;
6947 }
6948
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006949 //handle vr audio getparam
6950
6951 ret = str_parms_get_str(query,
6952 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6953 value, sizeof(value));
6954
6955 if (ret >= 0) {
6956 bool vr_audio_enabled = false;
6957 pthread_mutex_lock(&adev->lock);
6958 vr_audio_enabled = adev->vr_audio_mode_enabled;
6959 pthread_mutex_unlock(&adev->lock);
6960
6961 ALOGI("getting vr mode to %d", vr_audio_enabled);
6962
6963 if (vr_audio_enabled) {
6964 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6965 "true");
6966 goto exit;
6967 } else {
6968 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6969 "false");
6970 goto exit;
6971 }
6972 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006973
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006974 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006975 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08006976 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006977 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05306978 pthread_mutex_unlock(&adev->lock);
6979
Naresh Tannirud7205b62014-06-20 02:54:48 +05306980exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006981 str = str_parms_to_str(reply);
6982 str_parms_destroy(query);
6983 str_parms_destroy(reply);
6984
6985 ALOGV("%s: exit: returns - %s", __func__, str);
6986 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006987}
6988
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006989static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006990{
6991 return 0;
6992}
6993
6994static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
6995{
Haynes Mathew George5191a852013-09-11 14:19:36 -07006996 int ret;
6997 struct audio_device *adev = (struct audio_device *)dev;
6998 pthread_mutex_lock(&adev->lock);
6999 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07007000 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07007001 pthread_mutex_unlock(&adev->lock);
7002 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007003}
7004
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007005static int adev_set_master_volume(struct audio_hw_device *dev __unused,
7006 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007007{
7008 return -ENOSYS;
7009}
7010
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007011static int adev_get_master_volume(struct audio_hw_device *dev __unused,
7012 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007013{
7014 return -ENOSYS;
7015}
7016
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007017static int adev_set_master_mute(struct audio_hw_device *dev __unused,
7018 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007019{
7020 return -ENOSYS;
7021}
7022
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007023static int adev_get_master_mute(struct audio_hw_device *dev __unused,
7024 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007025{
7026 return -ENOSYS;
7027}
7028
7029static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
7030{
7031 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07007032 struct listnode *node;
7033 struct audio_usecase *usecase = NULL;
7034 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007035 pthread_mutex_lock(&adev->lock);
7036 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007037 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007038 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08007039 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07007040 list_for_each(node, &adev->usecase_list) {
7041 usecase = node_to_item(node, struct audio_usecase, list);
7042 if (usecase->type == VOICE_CALL)
7043 break;
7044 }
7045 if (usecase &&
7046 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
7047 ret = audio_extn_usb_check_and_set_svc_int(usecase,
7048 true);
7049 if (ret != 0) {
7050 /* default service interval was successfully updated,
7051 reopen USB backend with new service interval */
7052 check_usecases_codec_backend(adev,
7053 usecase,
7054 usecase->out_snd_device);
7055 }
7056 }
7057
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007058 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07007059 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007060 adev->current_call_output = NULL;
7061 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007062 }
7063 pthread_mutex_unlock(&adev->lock);
7064 return 0;
7065}
7066
7067static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
7068{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007069 int ret;
7070
7071 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08007072 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007073 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Derek Chencdd17c72014-11-24 12:39:14 -08007074 if (adev->ext_hw_plugin)
7075 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007076 pthread_mutex_unlock(&adev->lock);
7077
7078 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007079}
7080
7081static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
7082{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007083 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007084 return 0;
7085}
7086
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007087static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007088 const struct audio_config *config)
7089{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007090 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007092 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
7093 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007094}
7095
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007096static bool adev_input_allow_hifi_record(struct audio_device *adev,
7097 audio_devices_t devices,
7098 audio_input_flags_t flags,
7099 audio_source_t source) {
7100 const bool allowed = true;
7101
7102 if (!audio_is_usb_in_device(devices))
7103 return !allowed;
7104
7105 switch (flags) {
7106 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007107 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07007108 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7109 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007110 default:
7111 return !allowed;
7112 }
7113
7114 switch (source) {
7115 case AUDIO_SOURCE_DEFAULT:
7116 case AUDIO_SOURCE_MIC:
7117 case AUDIO_SOURCE_UNPROCESSED:
7118 break;
7119 default:
7120 return !allowed;
7121 }
7122
7123 switch (adev->mode) {
7124 case 0:
7125 break;
7126 default:
7127 return !allowed;
7128 }
7129
7130 return allowed;
7131}
7132
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007133static int adev_update_voice_comm_input_stream(struct stream_in *in,
7134 struct audio_config *config)
7135{
7136 bool valid_rate = (config->sample_rate == 8000 ||
7137 config->sample_rate == 16000 ||
7138 config->sample_rate == 32000 ||
7139 config->sample_rate == 48000);
7140 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
7141
7142#ifndef COMPRESS_VOIP_ENABLED
kunleizd96526c2018-04-09 11:12:32 +08007143 if (valid_rate && valid_ch &&
7144 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007145 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7146 in->config = default_pcm_config_voip_copp;
7147 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
7148 DEFAULT_VOIP_BUF_DURATION_MS,
7149 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
7150 } else {
kunleizbdd9ad02018-04-24 10:53:17 +08007151 ALOGW("%s No valid input in voip, use defaults"
7152 "sample rate %u, channel mask 0x%X",
7153 __func__, config->sample_rate, in->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007154 }
7155 in->config.rate = config->sample_rate;
7156 in->sample_rate = config->sample_rate;
7157#else
7158 //XXX needed for voice_extn_compress_voip_open_input_stream
7159 in->config.rate = config->sample_rate;
7160 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7161 voice_extn_compress_voip_is_active(in->dev)) &&
7162 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7163 valid_rate && valid_ch) {
7164 voice_extn_compress_voip_open_input_stream(in);
7165 // update rate entries to match config from AF
7166 in->config.rate = config->sample_rate;
7167 in->sample_rate = config->sample_rate;
7168 } else {
7169 ALOGW("%s compress voip not active, use defaults", __func__);
7170 }
7171#endif
7172 return 0;
7173}
7174
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007175static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007176 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007177 audio_devices_t devices,
7178 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007179 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307180 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007181 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007182 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007183{
7184 struct audio_device *adev = (struct audio_device *)dev;
7185 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007186 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007187 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007188 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05307189 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007190 bool is_usb_dev = audio_is_usb_in_device(devices);
7191 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
7192 devices,
7193 flags,
7194 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307195
kunleizdff872d2018-08-20 14:40:33 +08007196 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007197 is_usb_dev = false;
7198 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
7199 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
7200 __func__, devices);
7201 }
7202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007203 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007204
7205 if (!(is_usb_dev && may_use_hifi_record)) {
7206 if (config->sample_rate == 0)
7207 config->sample_rate = 48000;
7208 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7209 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7210 if (config->format == AUDIO_FORMAT_DEFAULT)
7211 config->format = AUDIO_FORMAT_PCM_16_BIT;
7212
7213 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
7214
7215 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
7216 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05307217 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007218
7219 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007220
7221 if (!in) {
7222 ALOGE("failed to allocate input stream");
7223 return -ENOMEM;
7224 }
7225
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307226 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307227 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7228 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007229 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007230 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007231
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007232 in->stream.common.get_sample_rate = in_get_sample_rate;
7233 in->stream.common.set_sample_rate = in_set_sample_rate;
7234 in->stream.common.get_buffer_size = in_get_buffer_size;
7235 in->stream.common.get_channels = in_get_channels;
7236 in->stream.common.get_format = in_get_format;
7237 in->stream.common.set_format = in_set_format;
7238 in->stream.common.standby = in_standby;
7239 in->stream.common.dump = in_dump;
7240 in->stream.common.set_parameters = in_set_parameters;
7241 in->stream.common.get_parameters = in_get_parameters;
7242 in->stream.common.add_audio_effect = in_add_audio_effect;
7243 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7244 in->stream.set_gain = in_set_gain;
7245 in->stream.read = in_read;
7246 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307247 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007248
7249 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007250 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007251 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007252 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007253 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007254 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007255 in->bit_width = 16;
7256 in->af_period_multiplier = 1;
7257
7258 /* Update config params with the requested sample rate and channels */
7259 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
7260 (adev->mode != AUDIO_MODE_IN_CALL)) {
7261 ret = -EINVAL;
7262 goto err_open;
7263 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007264
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007265 if (is_usb_dev && may_use_hifi_record) {
7266 /* HiFi record selects an appropriate format, channel, rate combo
7267 depending on sink capabilities*/
7268 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7269 &config->format,
7270 &in->supported_formats[0],
7271 MAX_SUPPORTED_FORMATS,
7272 &config->channel_mask,
7273 &in->supported_channel_masks[0],
7274 MAX_SUPPORTED_CHANNEL_MASKS,
7275 &config->sample_rate,
7276 &in->supported_sample_rates[0],
7277 MAX_SUPPORTED_SAMPLE_RATES);
7278 if (ret != 0) {
7279 ret = -EINVAL;
7280 goto err_open;
7281 }
7282 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007283 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307284 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05307285 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
7286 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
7287 in->config.format = PCM_FORMAT_S32_LE;
7288 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307289 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
7290 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
7291 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
7292 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7293 bool ret_error = false;
7294 in->bit_width = 24;
7295 /* 24 bit is restricted to UNPROCESSED source only,also format supported
7296 from HAL is 24_packed and 8_24
7297 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
7298 24_packed return error indicating supported format is 24_packed
7299 *> In case of any other source requesting 24 bit or float return error
7300 indicating format supported is 16 bit only.
7301
7302 on error flinger will retry with supported format passed
7303 */
7304 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
7305 (source != AUDIO_SOURCE_CAMCORDER)) {
7306 config->format = AUDIO_FORMAT_PCM_16_BIT;
7307 if (config->sample_rate > 48000)
7308 config->sample_rate = 48000;
7309 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07007310 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
7311 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307312 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
7313 ret_error = true;
7314 }
7315
7316 if (ret_error) {
7317 ret = -EINVAL;
7318 goto err_open;
7319 }
7320 }
7321
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007322 in->channel_mask = config->channel_mask;
7323 in->format = config->format;
7324
7325 in->usecase = USECASE_AUDIO_RECORD;
7326 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
7327 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
7328 is_low_latency = true;
7329#if LOW_LATENCY_CAPTURE_USE_CASE
7330 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
7331#endif
7332 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
7333 }
7334
7335 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
7336 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
7337 in->realtime = 0;
7338 in->usecase = USECASE_AUDIO_RECORD_MMAP;
7339 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07007340 in->config.format = pcm_format_from_audio_format(config->format);
Weiyin Jiangde7925e2018-11-27 18:45:53 +08007341 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007342 in->stream.start = in_start;
7343 in->stream.stop = in_stop;
7344 in->stream.create_mmap_buffer = in_create_mmap_buffer;
7345 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007346 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007347 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
7348 } else if (in->realtime) {
7349 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07007350 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007351 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007352 in->sample_rate = in->config.rate;
7353 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07007354 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007355 in->usecase = USECASE_AUDIO_RECORD_HIFI;
7356 in->config = pcm_config_audio_capture;
7357 frame_size = audio_stream_in_frame_size(&in->stream);
7358 buffer_size = get_input_buffer_size(config->sample_rate,
7359 config->format,
7360 channel_count,
7361 false /*is_low_latency*/);
7362 in->config.period_size = buffer_size / frame_size;
7363 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007364 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07007365 switch (config->format) {
7366 case AUDIO_FORMAT_PCM_32_BIT:
7367 in->bit_width = 32;
7368 break;
7369 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
7370 case AUDIO_FORMAT_PCM_8_24_BIT:
7371 in->bit_width = 24;
7372 break;
7373 default:
7374 in->bit_width = 16;
7375 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007376 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007377 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007378 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05307379 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007380 if (config->sample_rate == 0)
7381 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7382 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
7383 config->sample_rate != 8000) {
7384 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7385 ret = -EINVAL;
7386 goto err_open;
7387 }
7388 if (config->format == AUDIO_FORMAT_DEFAULT)
7389 config->format = AUDIO_FORMAT_PCM_16_BIT;
7390 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
7391 config->format = AUDIO_FORMAT_PCM_16_BIT;
7392 ret = -EINVAL;
7393 goto err_open;
7394 }
7395
7396 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
7397 in->config = pcm_config_afe_proxy_record;
7398 in->config.channels = channel_count;
7399 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307400 in->sample_rate = config->sample_rate;
Haynes Mathew George46740472017-10-27 18:40:12 -07007401 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05307402 int ret_val;
7403 pthread_mutex_lock(&adev->lock);
7404 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
7405 in, config, &channel_mask_updated);
7406 pthread_mutex_unlock(&adev->lock);
7407
7408 if (!ret_val) {
7409 if (channel_mask_updated == true) {
7410 ALOGD("%s: return error to retry with updated channel mask (%#x)",
7411 __func__, config->channel_mask);
7412 ret = -EINVAL;
7413 goto err_open;
7414 }
7415 ALOGD("%s: created multi-channel session succesfully",__func__);
7416 } else if (audio_extn_compr_cap_enabled() &&
7417 audio_extn_compr_cap_format_supported(config->format) &&
7418 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
7419 audio_extn_compr_cap_init(in);
7420 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05307421 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05307422 ret = audio_extn_cin_configure_input_stream(in);
7423 if (ret)
7424 goto err_open;
7425 } else {
7426 in->config = pcm_config_audio_capture;
7427 in->config.rate = config->sample_rate;
7428 in->config.format = pcm_format_from_audio_format(config->format);
7429 in->config.channels = channel_count;
7430 in->sample_rate = config->sample_rate;
7431 in->format = config->format;
7432 frame_size = audio_stream_in_frame_size(&in->stream);
7433 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07007434 config->format,
7435 channel_count,
7436 is_low_latency);
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
kunleiz8405edd2018-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 Chencdd17c72014-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);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007618
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 Chencdd17c72014-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};