blob: 8f27e864e538b5aa7c693d12b656ae91825ad9c8 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Dhanalakshmi Siddani0f1dfd52019-01-09 12:38:13 +05302 * Copyright (c) 2013-2019, 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
Vatsal Buchaa1358992018-11-14 13:25:08 +0530451#ifdef AUDIO_FEATURE_ENABLED_GCOV
452extern void __gcov_flush();
453static void enable_gcov()
454{
455 __gcov_flush();
456}
457#else
458static void enable_gcov()
459{
460}
461#endif
462
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700463static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
464 int flags __unused)
465{
466 int dir = 0;
467 switch (uc_id) {
468 case USECASE_AUDIO_RECORD_LOW_LATENCY:
469 dir = 1;
470 case USECASE_AUDIO_PLAYBACK_ULL:
471 break;
472 default:
473 return false;
474 }
475
476 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
477 PCM_PLAYBACK : PCM_CAPTURE);
478 if (adev->adm_is_noirq_avail)
479 return adev->adm_is_noirq_avail(adev->adm_data,
480 adev->snd_card, dev_id, dir);
481 return false;
482}
483
484static void register_out_stream(struct stream_out *out)
485{
486 struct audio_device *adev = out->dev;
487 if (is_offload_usecase(out->usecase) ||
488 !adev->adm_register_output_stream)
489 return;
490
491 // register stream first for backward compatibility
492 adev->adm_register_output_stream(adev->adm_data,
493 out->handle,
494 out->flags);
495
496 if (!adev->adm_set_config)
497 return;
498
499 if (out->realtime)
500 adev->adm_set_config(adev->adm_data,
501 out->handle,
502 out->pcm, &out->config);
503}
504
505static void register_in_stream(struct stream_in *in)
506{
507 struct audio_device *adev = in->dev;
508 if (!adev->adm_register_input_stream)
509 return;
510
511 adev->adm_register_input_stream(adev->adm_data,
512 in->capture_handle,
513 in->flags);
514
515 if (!adev->adm_set_config)
516 return;
517
518 if (in->realtime)
519 adev->adm_set_config(adev->adm_data,
520 in->capture_handle,
521 in->pcm,
522 &in->config);
523}
524
525static void request_out_focus(struct stream_out *out, long ns)
526{
527 struct audio_device *adev = out->dev;
528
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700529 if (adev->adm_request_focus_v2)
530 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
531 else if (adev->adm_request_focus)
532 adev->adm_request_focus(adev->adm_data, out->handle);
533}
534
535static void request_in_focus(struct stream_in *in, long ns)
536{
537 struct audio_device *adev = in->dev;
538
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700539 if (adev->adm_request_focus_v2)
540 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
541 else if (adev->adm_request_focus)
542 adev->adm_request_focus(adev->adm_data, in->capture_handle);
543}
544
545static void release_out_focus(struct stream_out *out)
546{
547 struct audio_device *adev = out->dev;
548
549 if (adev->adm_abandon_focus)
550 adev->adm_abandon_focus(adev->adm_data, out->handle);
551}
552
553static void release_in_focus(struct stream_in *in)
554{
555 struct audio_device *adev = in->dev;
556 if (adev->adm_abandon_focus)
557 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
558}
559
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530560static int parse_snd_card_status(struct str_parms *parms, int *card,
561 card_status_t *status)
562{
563 char value[32]={0};
564 char state[32]={0};
565
566 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
567 if (ret < 0)
568 return -1;
569
570 // sscanf should be okay as value is of max length 32.
571 // same as sizeof state.
572 if (sscanf(value, "%d,%s", card, state) < 2)
573 return -1;
574
575 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
576 CARD_STATUS_OFFLINE;
577 return 0;
578}
579
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700580static inline void adjust_frames_for_device_delay(struct stream_out *out,
581 uint32_t *dsp_frames) {
582 // Adjustment accounts for A2dp encoder latency with offload usecases
583 // Note: Encoder latency is returned in ms.
584 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
585 unsigned long offset =
586 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
587 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
588 }
589}
590
vivek mehtaa76401a2015-04-24 14:12:15 -0700591__attribute__ ((visibility ("default")))
592bool audio_hw_send_gain_dep_calibration(int level) {
593 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700594 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700595
596 pthread_mutex_lock(&adev_init_lock);
597
598 if (adev != NULL && adev->platform != NULL) {
599 pthread_mutex_lock(&adev->lock);
600 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700601
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530602 // cache level info for any of the use case which
603 // was not started.
604 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700605
vivek mehtaa76401a2015-04-24 14:12:15 -0700606 pthread_mutex_unlock(&adev->lock);
607 } else {
608 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
609 }
610
611 pthread_mutex_unlock(&adev_init_lock);
612
613 return ret_val;
614}
615
Ashish Jain5106d362016-05-11 19:23:33 +0530616static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
617{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800618 bool gapless_enabled = false;
619 const char *mixer_ctl_name = "Compress Gapless Playback";
620 struct mixer_ctl *ctl;
621
622 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700623 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530624
625 /*Disable gapless if its AV playback*/
626 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800627
628 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
629 if (!ctl) {
630 ALOGE("%s: Could not get ctl for mixer cmd - %s",
631 __func__, mixer_ctl_name);
632 return -EINVAL;
633 }
634
635 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
636 ALOGE("%s: Could not set gapless mode %d",
637 __func__, gapless_enabled);
638 return -EINVAL;
639 }
640 return 0;
641}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700642
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700643__attribute__ ((visibility ("default")))
644int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
645 int table_size) {
646 int ret_val = 0;
647 ALOGV("%s: enter ... ", __func__);
648
649 pthread_mutex_lock(&adev_init_lock);
650 if (adev == NULL) {
651 ALOGW("%s: adev is NULL .... ", __func__);
652 goto done;
653 }
654
655 pthread_mutex_lock(&adev->lock);
656 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
657 pthread_mutex_unlock(&adev->lock);
658done:
659 pthread_mutex_unlock(&adev_init_lock);
660 ALOGV("%s: exit ... ", __func__);
661 return ret_val;
662}
663
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700664static bool is_supported_format(audio_format_t format)
665{
Eric Laurent86e17132013-09-12 17:49:30 -0700666 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530667 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530668 format == AUDIO_FORMAT_AAC_LC ||
669 format == AUDIO_FORMAT_AAC_HE_V1 ||
670 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530671 format == AUDIO_FORMAT_AAC_ADTS_LC ||
672 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
673 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530674 format == AUDIO_FORMAT_AAC_LATM_LC ||
675 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
676 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530677 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
678 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530679 format == AUDIO_FORMAT_PCM_FLOAT ||
680 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700681 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530682 format == AUDIO_FORMAT_AC3 ||
683 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700684 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530685 format == AUDIO_FORMAT_DTS ||
686 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800687 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530688 format == AUDIO_FORMAT_ALAC ||
689 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530690 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530691 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800692 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530693 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700694 format == AUDIO_FORMAT_APTX ||
695 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800696 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700697
698 return false;
699}
700
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700701static inline bool is_mmap_usecase(audio_usecase_t uc_id)
702{
703 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
704 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
705}
706
Avinash Vaish71a8b972014-07-24 15:36:33 +0530707static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
708 struct audio_usecase *uc_info)
709{
710 struct listnode *node;
711 struct audio_usecase *usecase;
712
713 if (uc_info == NULL)
714 return -EINVAL;
715
716 /* Re-route all voice usecases on the shared backend other than the
717 specified usecase to new snd devices */
718 list_for_each(node, &adev->usecase_list) {
719 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800720 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530721 enable_audio_route(adev, usecase);
722 }
723 return 0;
724}
725
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530726static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530727{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530728 ALOGV("%s", __func__);
729 audio_route_apply_and_update_path(adev->audio_route,
730 "asrc-mode");
731 adev->asrc_mode_enabled = true;
732}
733
734static void disable_asrc_mode(struct audio_device *adev)
735{
736 ALOGV("%s", __func__);
737 audio_route_reset_and_update_path(adev->audio_route,
738 "asrc-mode");
739 adev->asrc_mode_enabled = false;
740}
741
742/*
743 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
744 * 44.1 or Native DSD backends are enabled for any of current use case.
745 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
746 * - Disable current mix path use case(Headphone backend) and re-enable it with
747 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
748 * e.g. Naitve DSD or Headphone 44.1 -> + 48
749 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530750static void check_and_set_asrc_mode(struct audio_device *adev,
751 struct audio_usecase *uc_info,
752 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530753{
754 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530755 int i, num_new_devices = 0;
756 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
757 /*
758 *Split snd device for new combo use case
759 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
760 */
761 if (platform_split_snd_device(adev->platform,
762 snd_device,
763 &num_new_devices,
764 split_new_snd_devices) == 0) {
765 for (i = 0; i < num_new_devices; i++)
766 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
767 } else {
768 int new_backend_idx = platform_get_backend_index(snd_device);
769 if (((new_backend_idx == HEADPHONE_BACKEND) ||
770 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
771 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
772 !adev->asrc_mode_enabled) {
773 struct listnode *node = NULL;
774 struct audio_usecase *uc = NULL;
775 struct stream_out *curr_out = NULL;
776 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
777 int i, num_devices, ret = 0;
778 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530779
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530780 list_for_each(node, &adev->usecase_list) {
781 uc = node_to_item(node, struct audio_usecase, list);
782 curr_out = (struct stream_out*) uc->stream.out;
783 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
784 /*
785 *Split snd device for existing combo use case
786 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
787 */
788 ret = platform_split_snd_device(adev->platform,
789 uc->out_snd_device,
790 &num_devices,
791 split_snd_devices);
792 if (ret < 0 || num_devices == 0) {
793 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
794 split_snd_devices[0] = uc->out_snd_device;
795 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800796 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530797 for (i = 0; i < num_devices; i++) {
798 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
799 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
800 if((new_backend_idx == HEADPHONE_BACKEND) &&
801 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
802 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
803 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
804 __func__);
805 enable_asrc_mode(adev);
806 break;
807 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
808 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
809 (usecase_backend_idx == HEADPHONE_BACKEND)) {
810 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
811 __func__);
812 disable_audio_route(adev, uc);
813 disable_snd_device(adev, uc->out_snd_device);
814 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
815 if (new_backend_idx == DSD_NATIVE_BACKEND)
816 audio_route_apply_and_update_path(adev->audio_route,
817 "hph-true-highquality-mode");
818 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
819 (curr_out->bit_width >= 24))
820 audio_route_apply_and_update_path(adev->audio_route,
821 "hph-highquality-mode");
822 enable_asrc_mode(adev);
823 enable_snd_device(adev, uc->out_snd_device);
824 enable_audio_route(adev, uc);
825 break;
826 }
827 }
828 // reset split devices count
829 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800830 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530831 if (adev->asrc_mode_enabled)
832 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530833 }
834 }
835 }
836}
837
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700838#ifdef DYNAMIC_ECNS_ENABLED
839static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
840 struct audio_effect_config effect_config,
841 unsigned int param_value)
842{
843 char mixer_ctl_name[] = "Audio Effect";
844 struct mixer_ctl *ctl;
845 long set_values[6];
846 struct stream_in *in = adev->active_input;
847
848 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
849 if (!ctl) {
850 ALOGE("%s: Could not get mixer ctl - %s",
851 __func__, mixer_ctl_name);
852 return -EINVAL;
853 }
854
855 set_values[0] = 1; //0:Rx 1:Tx
856 set_values[1] = in->app_type_cfg.app_type;
857 set_values[2] = (long)effect_config.module_id;
858 set_values[3] = (long)effect_config.instance_id;
859 set_values[4] = (long)effect_config.param_id;
860 set_values[5] = param_value;
861
862 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
863
864 return 0;
865
866}
867
868static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
869 int effect_type, unsigned int *param_value)
870{
871 int ret = 0;
872 struct audio_effect_config other_effect_config;
873 struct audio_usecase *usecase = NULL;
874 struct stream_in *in = adev->active_input;
875
876 usecase = get_usecase_from_list(adev, in->usecase);
877 if (!usecase)
878 return -EINVAL;
879
880 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
881 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
882 if (ret < 0) {
883 ALOGE("%s Failed to get effect params %d", __func__, ret);
884 return ret;
885 }
886
887 if (module_id == other_effect_config.module_id) {
888 //Same module id for AEC/NS. Values need to be combined
889 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
890 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
891 *param_value |= other_effect_config.param_value;
892 }
893 }
894
895 return ret;
896}
897
898static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
899{
900 struct audio_effect_config effect_config;
901 struct audio_usecase *usecase = NULL;
902 int ret = 0;
903 unsigned int param_value = 0;
904 struct stream_in *in = adev->active_input;
905
906 if (!in) {
907 ALOGE("%s: Invalid input stream", __func__);
908 return -EINVAL;
909 }
910
911 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
912
913 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800914 if (usecase == NULL) {
915 ALOGE("%s: Could not find the usecase (%d) in the list",
916 __func__, in->usecase);
917 return -EINVAL;
918 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700919
920 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
921 if (ret < 0) {
922 ALOGE("%s Failed to get module id %d", __func__, ret);
923 return ret;
924 }
925 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
926 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
927
928 if(enable)
929 param_value = effect_config.param_value;
930
931 /*Special handling for AEC & NS effects Param values need to be
932 updated if module ids are same*/
933
934 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
935 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
936 if (ret < 0)
937 return ret;
938 }
939
940 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
941
942 return ret;
943}
944
945static void check_and_enable_effect(struct audio_device *adev)
946{
947
948 if (adev->active_input->enable_aec) {
949 enable_disable_effect(adev, EFFECT_AEC, true);
950 }
951
952 if (adev->active_input->enable_ns &&
953 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
954 enable_disable_effect(adev, EFFECT_NS, true);
955 }
956}
957#else
958#define enable_disable_effect(x, y, z) ENOSYS
959#define check_and_enable_effect(x) ENOSYS
960#endif
961
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700962int pcm_ioctl(struct pcm *pcm, int request, ...)
963{
964 va_list ap;
965 void * arg;
966 int pcm_fd = *(int*)pcm;
967
968 va_start(ap, request);
969 arg = va_arg(ap, void *);
970 va_end(ap);
971
972 return ioctl(pcm_fd, request, arg);
973}
974
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700975int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700976 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800977{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700978 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700979 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530980 struct stream_out *out = NULL;
Soumya Managolie7651c42018-06-28 16:04:57 +0530981 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800982
983 if (usecase == NULL)
984 return -EINVAL;
985
986 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
987
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800988 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700989 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800990 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700991 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800992
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800993#ifdef DS1_DOLBY_DAP_ENABLED
994 audio_extn_dolby_set_dmid(adev);
995 audio_extn_dolby_set_endpoint(adev);
996#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700997 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700998 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530999 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001000 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301001 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301002 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1003 out = usecase->stream.out;
1004 if (out && out->compr)
1005 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1006 }
Dhananjay Kumar2a7f75b2018-12-10 22:26:53 +05301007 audio_extn_set_custom_mtmx_params(adev, usecase, true);
Manish Dewangan58229382017-02-02 15:48:41 +05301008
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001009 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001010 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001011 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managolie7651c42018-06-28 16:04:57 +05301012 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1013 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1014 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1015 if (parms) {
1016 audio_extn_fm_set_parameters(adev, parms);
1017 str_parms_destroy(parms);
1018 }
1019 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001020 ALOGV("%s: exit", __func__);
1021 return 0;
1022}
1023
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001024int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001025 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001026{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001027 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001028 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001029
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301030 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001031 return -EINVAL;
1032
1033 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001034 if (usecase->type == PCM_CAPTURE)
1035 snd_device = usecase->in_snd_device;
1036 else
1037 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001038 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001039 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001040 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001041 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001042 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301043 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Dhananjay Kumar2a7f75b2018-12-10 22:26:53 +05301044 audio_extn_set_custom_mtmx_params(adev, usecase, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001045 ALOGV("%s: exit", __func__);
1046 return 0;
1047}
1048
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001049int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001050 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001051{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301052 int i, num_devices = 0;
1053 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001054 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1055
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001056 if (snd_device < SND_DEVICE_MIN ||
1057 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001058 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001059 return -EINVAL;
1060 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001061
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001062 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001063 ALOGE("%s: Invalid sound device returned", __func__);
1064 return -EINVAL;
1065 }
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001066
1067 adev->snd_dev_ref_cnt[snd_device]++;
1068
1069 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1070 (platform_split_snd_device(adev->platform,
1071 snd_device,
1072 &num_devices,
1073 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001074 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001075 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001076 return 0;
1077 }
1078
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001079 if (audio_extn_spkr_prot_is_enabled())
1080 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001081
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001082 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1083 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001084 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1085 goto err;
1086 }
1087 audio_extn_dev_arbi_acquire(snd_device);
1088 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001089 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001090 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001091 goto err;
1092 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001093 } else if (platform_split_snd_device(adev->platform,
1094 snd_device,
1095 &num_devices,
1096 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301097 for (i = 0; i < num_devices; i++) {
1098 enable_snd_device(adev, new_snd_devices[i]);
1099 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001100 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001101 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301102
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301103
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001104 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1105 (audio_extn_a2dp_start_playback() < 0)) {
1106 ALOGE(" fail to configure A2dp control path ");
1107 goto err;
1108 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301109
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001110 /* due to the possibility of calibration overwrite between listen
1111 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001112 audio_extn_sound_trigger_update_device_status(snd_device,
1113 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301114 audio_extn_listen_update_device_status(snd_device,
1115 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001116 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001117 audio_extn_sound_trigger_update_device_status(snd_device,
1118 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301119 audio_extn_listen_update_device_status(snd_device,
1120 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001121 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001122 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001123 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001124 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301125
1126 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1127 !adev->native_playback_enabled &&
1128 audio_is_true_native_stream_active(adev)) {
1129 ALOGD("%s: %d: napb: enabling native mode in hardware",
1130 __func__, __LINE__);
1131 audio_route_apply_and_update_path(adev->audio_route,
1132 "true-native-mode");
1133 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301134 }
Dhanalakshmi Siddani0f1dfd52019-01-09 12:38:13 +05301135 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1136 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001137 (audio_extn_ffv_get_stream() == adev->active_input)) {
1138 ALOGD("%s: init ec ref loopback", __func__);
1139 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1140 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001141 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001142 return 0;
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001143err:
1144 adev->snd_dev_ref_cnt[snd_device]--;
1145 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001146}
1147
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001148int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001149 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001150{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301151 int i, num_devices = 0;
1152 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001153 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1154
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001155 if (snd_device < SND_DEVICE_MIN ||
1156 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001157 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001158 return -EINVAL;
1159 }
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001160
1161 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1162 ALOGE("%s: Invalid sound device returned", __func__);
1163 return -EINVAL;
1164 }
1165
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001166 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1167 ALOGE("%s: device ref cnt is already 0", __func__);
1168 return -EINVAL;
1169 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001170
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001171 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001172
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001173 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001174 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301175
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001176 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1177 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001178 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001179
1180 // when speaker device is disabled, reset swap.
1181 // will be renabled on usecase start
1182 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001183 } else if (platform_split_snd_device(adev->platform,
1184 snd_device,
1185 &num_devices,
1186 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301187 for (i = 0; i < num_devices; i++) {
1188 disable_snd_device(adev, new_snd_devices[i]);
1189 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001190 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001191 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001192 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001193
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301194 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1195 audio_extn_a2dp_stop_playback();
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001196 else if (snd_device == SND_DEVICE_OUT_HDMI ||
1197 snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301198 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301199 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001200 adev->native_playback_enabled) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301201 ALOGD("%s: %d: napb: disabling native mode in hardware",
1202 __func__, __LINE__);
1203 audio_route_reset_and_update_path(adev->audio_route,
1204 "true-native-mode");
1205 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301206 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001207 adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301208 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301209 disable_asrc_mode(adev);
1210 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001211 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1212 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
1213 (audio_extn_ffv_get_stream() == adev->active_input)) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001214 ALOGD("%s: deinit ec ref loopback", __func__);
1215 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1216 }
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001217
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001218 audio_extn_utils_release_snd_device(snd_device);
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001219 } else {
1220 if (platform_split_snd_device(adev->platform,
1221 snd_device,
1222 &num_devices,
1223 new_snd_devices) == 0) {
1224 for (i = 0; i < num_devices; i++) {
1225 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1226 }
1227 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001228 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001230 return 0;
1231}
1232
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001233/*
1234 legend:
1235 uc - existing usecase
1236 new_uc - new usecase
1237 d1, d11, d2 - SND_DEVICE enums
1238 a1, a2 - corresponding ANDROID device enums
1239 B1, B2 - backend strings
1240
1241case 1
1242 uc->dev d1 (a1) B1
1243 new_uc->dev d1 (a1), d2 (a2) B1, B2
1244
1245 resolution: disable and enable uc->dev on d1
1246
1247case 2
1248 uc->dev d1 (a1) B1
1249 new_uc->dev d11 (a1) B1
1250
1251 resolution: need to switch uc since d1 and d11 are related
1252 (e.g. speaker and voice-speaker)
1253 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1254
1255case 3
1256 uc->dev d1 (a1) B1
1257 new_uc->dev d2 (a2) B2
1258
1259 resolution: no need to switch uc
1260
1261case 4
1262 uc->dev d1 (a1) B1
1263 new_uc->dev d2 (a2) B1
1264
1265 resolution: disable enable uc-dev on d2 since backends match
1266 we cannot enable two streams on two different devices if they
1267 share the same backend. e.g. if offload is on speaker device using
1268 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1269 using the same backend, offload must also be switched to voice-handset.
1270
1271case 5
1272 uc->dev d1 (a1) B1
1273 new_uc->dev d1 (a1), d2 (a2) B1
1274
1275 resolution: disable enable uc-dev on d2 since backends match
1276 we cannot enable two streams on two different devices if they
1277 share the same backend.
1278
1279case 6
1280 uc->dev d1 (a1) B1
1281 new_uc->dev d2 (a1) B2
1282
1283 resolution: no need to switch
1284
1285case 7
1286 uc->dev d1 (a1), d2 (a2) B1, B2
1287 new_uc->dev d1 (a1) B1
1288
1289 resolution: no need to switch
1290
Zhou Song4ba65882018-07-09 14:48:07 +08001291case 8
1292 uc->dev d1 (a1) B1
1293 new_uc->dev d11 (a1), d2 (a2) B1, B2
1294 resolution: compared to case 1, for this case, d1 and d11 are related
1295 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001296*/
1297static snd_device_t derive_playback_snd_device(void * platform,
1298 struct audio_usecase *uc,
1299 struct audio_usecase *new_uc,
1300 snd_device_t new_snd_device)
1301{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301302 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001303
1304 snd_device_t d1 = uc->out_snd_device;
1305 snd_device_t d2 = new_snd_device;
1306
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301307 switch (uc->type) {
1308 case TRANSCODE_LOOPBACK :
1309 a1 = uc->stream.inout->out_config.devices;
1310 a2 = new_uc->stream.inout->out_config.devices;
1311 break;
1312 default :
1313 a1 = uc->stream.out->devices;
1314 a2 = new_uc->stream.out->devices;
1315 break;
1316 }
1317
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001318 // Treat as a special case when a1 and a2 are not disjoint
1319 if ((a1 != a2) && (a1 & a2)) {
1320 snd_device_t d3[2];
1321 int num_devices = 0;
1322 int ret = platform_split_snd_device(platform,
1323 popcount(a1) > 1 ? d1 : d2,
1324 &num_devices,
1325 d3);
1326 if (ret < 0) {
1327 if (ret != -ENOSYS) {
1328 ALOGW("%s failed to split snd_device %d",
1329 __func__,
1330 popcount(a1) > 1 ? d1 : d2);
1331 }
1332 goto end;
1333 }
1334
1335 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1336 // But if it does happen, we need to give priority to d2 if
1337 // the combo devices active on the existing usecase share a backend.
1338 // This is because we cannot have a usecase active on a combo device
1339 // and a new usecase requests one device in this combo pair.
1340 if (platform_check_backends_match(d3[0], d3[1])) {
1341 return d2; // case 5
1342 } else {
Zhou Song671be042018-08-27 15:33:52 +08001343 // check if d1 is related to any of d3's OR
1344 // old uc is combo device but new_uc is one of the combo device
1345 if (d1 == d3[0] || d1 == d3[1] || popcount(a1) > 1)
1346 return d1; // case 1, 7
Zhou Song4ba65882018-07-09 14:48:07 +08001347 else
1348 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001349 }
1350 } else {
1351 if (platform_check_backends_match(d1, d2)) {
1352 return d2; // case 2, 4
1353 } else {
1354 return d1; // case 6, 3
1355 }
1356 }
1357
1358end:
1359 return d2; // return whatever was calculated before.
1360}
1361
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001362static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301363 struct audio_usecase *uc_info,
1364 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001365{
1366 struct listnode *node;
1367 struct audio_usecase *usecase;
1368 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301369 snd_device_t uc_derive_snd_device;
1370 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001371 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1372 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001373 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301374 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001375 /*
1376 * This function is to make sure that all the usecases that are active on
1377 * the hardware codec backend are always routed to any one device that is
1378 * handled by the hardware codec.
1379 * For example, if low-latency and deep-buffer usecases are currently active
1380 * on speaker and out_set_parameters(headset) is received on low-latency
1381 * output, then we have to make sure deep-buffer is also switched to headset,
1382 * because of the limitation that both the devices cannot be enabled
1383 * at the same time as they share the same backend.
1384 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001385 /*
1386 * This call is to check if we need to force routing for a particular stream
1387 * If there is a backend configuration change for the device when a
1388 * new stream starts, then ADM needs to be closed and re-opened with the new
1389 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001390 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001391 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001392 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1393 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301394 /* For a2dp device reconfigure all active sessions
1395 * with new AFE encoder format based on a2dp state
1396 */
1397 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1398 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1399 audio_extn_a2dp_is_force_device_switch()) {
1400 force_routing = true;
1401 force_restart_session = true;
1402 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301403 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1404
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001405 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001406 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001407 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001408 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1409 switch_device[i] = false;
1410
1411 list_for_each(node, &adev->usecase_list) {
1412 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001413
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301414 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1415 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301416 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301417 platform_get_snd_device_name(usecase->out_snd_device),
1418 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301419 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1420 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1421 usecase, uc_info, snd_device);
1422 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1423 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1424 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1425 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001426 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301427 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1428 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1429 ((force_restart_session) ||
1430 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301431 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1432 __func__, use_case_table[usecase->id],
1433 platform_get_snd_device_name(usecase->out_snd_device));
1434 disable_audio_route(adev, usecase);
1435 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301436 /* Enable existing usecase on derived playback device */
1437 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301438 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301439 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001440 }
1441 }
1442
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301443 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1444 num_uc_to_switch);
1445
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001446 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001447 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001448
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301449 /* Make sure the previous devices to be disabled first and then enable the
1450 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001451 list_for_each(node, &adev->usecase_list) {
1452 usecase = node_to_item(node, struct audio_usecase, list);
1453 if (switch_device[usecase->id]) {
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001454 /* Check if output sound device to be switched can be split and if any
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001455 of the split devices match with derived sound device */
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001456 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1457 &num_devices, split_snd_devices) == 0) {
1458 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001459 for (i = 0; i < num_devices; i++) {
1460 /* Disable devices that do not match with derived sound device */
1461 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1462 disable_snd_device(adev, split_snd_devices[i]);
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001463 }
1464 } else {
1465 disable_snd_device(adev, usecase->out_snd_device);
1466 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 }
1468 }
1469
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001470 list_for_each(node, &adev->usecase_list) {
1471 usecase = node_to_item(node, struct audio_usecase, list);
1472 if (switch_device[usecase->id]) {
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001473 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1474 &num_devices, split_snd_devices) == 0) {
1475 /* Enable derived sound device only if it does not match with
1476 one of the split sound devices. This is because the matching
1477 sound device was not disabled */
1478 bool should_enable = true;
1479 for (i = 0; i < num_devices; i++) {
1480 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1481 should_enable = false;
1482 break;
1483 }
1484 }
1485 if (should_enable)
1486 enable_snd_device(adev, derive_snd_device[usecase->id]);
1487 } else {
1488 enable_snd_device(adev, derive_snd_device[usecase->id]);
1489 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001490 }
1491 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001492
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001493 /* Re-route all the usecases on the shared backend other than the
1494 specified usecase to new snd devices */
1495 list_for_each(node, &adev->usecase_list) {
1496 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301497 /* Update the out_snd_device only before enabling the audio route */
1498 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301499 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301500 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301501 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301502 use_case_table[usecase->id],
1503 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001504 /* Update voc calibration before enabling VoIP route */
1505 if (usecase->type == VOIP_CALL)
1506 status = platform_switch_voice_call_device_post(adev->platform,
1507 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001508 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301509 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001510 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1511 out_set_voip_volume(&usecase->stream.out->stream,
1512 usecase->stream.out->volume_l,
1513 usecase->stream.out->volume_r);
1514 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301515 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001516 }
1517 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001518 }
1519}
1520
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301521static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001522 struct audio_usecase *uc_info,
1523 snd_device_t snd_device)
1524{
1525 struct listnode *node;
1526 struct audio_usecase *usecase;
1527 bool switch_device[AUDIO_USECASE_MAX];
1528 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301529 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001530 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001531
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301532 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1533 snd_device);
1534 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301535
1536 /*
1537 * Make sure out devices is checked against out codec backend device and
1538 * also in devices against in codec backend. Checking out device against in
1539 * codec backend or vice versa causes issues.
1540 */
1541 if (uc_info->type == PCM_CAPTURE)
1542 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001543 /*
1544 * This function is to make sure that all the active capture usecases
1545 * are always routed to the same input sound device.
1546 * For example, if audio-record and voice-call usecases are currently
1547 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1548 * is received for voice call then we have to make sure that audio-record
1549 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1550 * because of the limitation that two devices cannot be enabled
1551 * at the same time if they share the same backend.
1552 */
1553 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1554 switch_device[i] = false;
1555
1556 list_for_each(node, &adev->usecase_list) {
1557 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301558 /*
1559 * TODO: Enhance below condition to handle BT sco/USB multi recording
1560 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001561 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001562 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301563 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301564 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301565 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301566 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001567 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001568 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1569 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001570 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001571 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001572 switch_device[usecase->id] = true;
1573 num_uc_to_switch++;
1574 }
1575 }
1576
1577 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001578 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001579
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301580 /* Make sure the previous devices to be disabled first and then enable the
1581 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001582 list_for_each(node, &adev->usecase_list) {
1583 usecase = node_to_item(node, struct audio_usecase, list);
1584 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001585 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001586 }
1587 }
1588
1589 list_for_each(node, &adev->usecase_list) {
1590 usecase = node_to_item(node, struct audio_usecase, list);
1591 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001592 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001593 }
1594 }
1595
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001596 /* Re-route all the usecases on the shared backend other than the
1597 specified usecase to new snd devices */
1598 list_for_each(node, &adev->usecase_list) {
1599 usecase = node_to_item(node, struct audio_usecase, list);
1600 /* Update the in_snd_device only before enabling the audio route */
1601 if (switch_device[usecase->id] ) {
1602 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001603 if (usecase->type != VOICE_CALL) {
1604 /* Update voc calibration before enabling VoIP route */
1605 if (usecase->type == VOIP_CALL)
1606 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001607 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001608 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301609 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001610 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001611 }
1612 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001613 }
1614}
1615
Mingming Yin3a941d42016-02-17 18:08:05 -08001616static void reset_hdmi_sink_caps(struct stream_out *out) {
1617 int i = 0;
1618
1619 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1620 out->supported_channel_masks[i] = 0;
1621 }
1622 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1623 out->supported_formats[i] = 0;
1624 }
1625 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1626 out->supported_sample_rates[i] = 0;
1627 }
1628}
1629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001630/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001631static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632{
Mingming Yin3a941d42016-02-17 18:08:05 -08001633 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001634 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001635
Mingming Yin3a941d42016-02-17 18:08:05 -08001636 reset_hdmi_sink_caps(out);
1637
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001638 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001639 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001640 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001641 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001642 }
1643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001645 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001646 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001647 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001648 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1649 case 6:
1650 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1651 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1652 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1653 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1654 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1655 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001656 break;
1657 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001658 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001659 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660 break;
1661 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001662
1663 // check channel format caps
1664 i = 0;
1665 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1666 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1667 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1668 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1669 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1670 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1671 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1672 }
1673
Ben Romberger1aaaf862017-04-06 17:49:46 -07001674 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1675 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1676 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1677 }
1678
Mingming Yin3a941d42016-02-17 18:08:05 -08001679 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1680 ALOGV(":%s HDMI supports DTS format", __func__);
1681 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1682 }
1683
1684 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1685 ALOGV(":%s HDMI supports DTS HD format", __func__);
1686 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1687 }
1688
Naresh Tanniru928f0862017-04-07 16:44:23 -07001689 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1690 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1691 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1692 }
1693
Mingming Yin3a941d42016-02-17 18:08:05 -08001694
1695 // check sample rate caps
1696 i = 0;
1697 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1698 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1699 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1700 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1701 }
1702 }
1703
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001704 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705}
1706
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001707static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1708 uint32_t *supported_sample_rates __unused,
1709 uint32_t max_rates __unused)
1710{
1711 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1712 supported_sample_rates,
1713 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301714 ssize_t i = 0;
1715
1716 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001717 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1718 supported_sample_rates[i]);
1719 }
1720 return count;
1721}
1722
1723static inline int read_usb_sup_channel_masks(bool is_playback,
1724 audio_channel_mask_t *supported_channel_masks,
1725 uint32_t max_masks)
1726{
1727 int channels = audio_extn_usb_get_max_channels(is_playback);
1728 int channel_count;
1729 uint32_t num_masks = 0;
1730 if (channels > MAX_HIFI_CHANNEL_COUNT)
1731 channels = MAX_HIFI_CHANNEL_COUNT;
1732
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301733 channel_count = DEFAULT_CHANNEL_COUNT;
1734
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001735 if (is_playback) {
1736 // For playback we never report mono because the framework always outputs stereo
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001737 // audio_channel_out_mask_from_count() does return positional masks for channel counts
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301738 // above 2 but we want indexed masks here.
1739 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001740 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001741 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1742 // indexed mask
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301743 supported_channel_masks[num_masks++] = audio_channel_in_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001744 }
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301745
1746 for (channel_count = channels; ((channel_count >= DEFAULT_CHANNEL_COUNT) &&
1747 (num_masks < max_masks)); channel_count--) {
1748 supported_channel_masks[num_masks++] =
1749 audio_channel_mask_for_index_assignment_from_count(channel_count);
1750 }
1751
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001752 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1753 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1754 return num_masks;
1755}
1756
1757static inline int read_usb_sup_formats(bool is_playback __unused,
1758 audio_format_t *supported_formats,
1759 uint32_t max_formats __unused)
1760{
1761 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1762 switch (bitwidth) {
1763 case 24:
1764 // XXX : usb.c returns 24 for s24 and s24_le?
1765 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1766 break;
1767 case 32:
1768 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1769 break;
1770 case 16:
1771 default :
1772 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1773 break;
1774 }
1775 ALOGV("%s: %s supported format %d", __func__,
1776 is_playback ? "P" : "C", bitwidth);
1777 return 1;
1778}
1779
1780static inline int read_usb_sup_params_and_compare(bool is_playback,
1781 audio_format_t *format,
1782 audio_format_t *supported_formats,
1783 uint32_t max_formats,
1784 audio_channel_mask_t *mask,
1785 audio_channel_mask_t *supported_channel_masks,
1786 uint32_t max_masks,
1787 uint32_t *rate,
1788 uint32_t *supported_sample_rates,
1789 uint32_t max_rates) {
1790 int ret = 0;
1791 int num_formats;
1792 int num_masks;
1793 int num_rates;
1794 int i;
1795
1796 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1797 max_formats);
1798 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1799 max_masks);
1800
1801 num_rates = read_usb_sup_sample_rates(is_playback,
1802 supported_sample_rates, max_rates);
1803
1804#define LUT(table, len, what, dflt) \
1805 for (i=0; i<len && (table[i] != what); i++); \
1806 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1807
1808 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1809 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1810 LUT(supported_sample_rates, num_rates, *rate, 0);
1811
1812#undef LUT
1813 return ret < 0 ? -EINVAL : 0; // HACK TBD
1814}
1815
Alexy Josephb1379942016-01-29 15:49:38 -08001816audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001817 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001818{
1819 struct audio_usecase *usecase;
1820 struct listnode *node;
1821
1822 list_for_each(node, &adev->usecase_list) {
1823 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001824 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001825 ALOGV("%s: usecase id %d", __func__, usecase->id);
1826 return usecase->id;
1827 }
1828 }
1829 return USECASE_INVALID;
1830}
1831
Alexy Josephb1379942016-01-29 15:49:38 -08001832struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001833 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001834{
1835 struct audio_usecase *usecase;
1836 struct listnode *node;
1837
1838 list_for_each(node, &adev->usecase_list) {
1839 usecase = node_to_item(node, struct audio_usecase, list);
1840 if (usecase->id == uc_id)
1841 return usecase;
1842 }
1843 return NULL;
1844}
1845
Dhananjay Kumard4833242016-10-06 22:09:12 +05301846struct stream_in *get_next_active_input(const struct audio_device *adev)
1847{
1848 struct audio_usecase *usecase;
1849 struct listnode *node;
1850
1851 list_for_each_reverse(node, &adev->usecase_list) {
1852 usecase = node_to_item(node, struct audio_usecase, list);
1853 if (usecase->type == PCM_CAPTURE)
1854 return usecase->stream.in;
1855 }
1856 return NULL;
1857}
1858
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301859/*
1860 * is a true native playback active
1861 */
1862bool audio_is_true_native_stream_active(struct audio_device *adev)
1863{
1864 bool active = false;
1865 int i = 0;
1866 struct listnode *node;
1867
1868 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1869 ALOGV("%s:napb: not in true mode or non hdphones device",
1870 __func__);
1871 active = false;
1872 goto exit;
1873 }
1874
1875 list_for_each(node, &adev->usecase_list) {
1876 struct audio_usecase *uc;
1877 uc = node_to_item(node, struct audio_usecase, list);
1878 struct stream_out *curr_out =
1879 (struct stream_out*) uc->stream.out;
1880
1881 if (curr_out && PCM_PLAYBACK == uc->type) {
1882 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1883 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1884 uc->id, curr_out->sample_rate,
1885 curr_out->bit_width,
1886 platform_get_snd_device_name(uc->out_snd_device));
1887
1888 if (is_offload_usecase(uc->id) &&
1889 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1890 active = true;
1891 ALOGD("%s:napb:native stream detected", __func__);
1892 }
1893 }
1894 }
1895exit:
1896 return active;
1897}
1898
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001899uint32_t adev_get_dsp_bit_width_enforce_mode()
1900{
1901 if (adev == NULL) {
1902 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1903 return 0;
1904 }
1905 return adev->dsp_bit_width_enforce_mode;
1906}
1907
1908static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1909{
1910 char value[PROPERTY_VALUE_MAX];
1911 int trial;
1912 uint32_t dsp_bit_width_enforce_mode = 0;
1913
1914 if (!mixer) {
1915 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1916 __func__);
1917 return 0;
1918 }
1919
1920 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1921 value, NULL) > 0) {
1922 trial = atoi(value);
1923 switch (trial) {
1924 case 16:
1925 dsp_bit_width_enforce_mode = 16;
1926 break;
1927 case 24:
1928 dsp_bit_width_enforce_mode = 24;
1929 break;
1930 case 32:
1931 dsp_bit_width_enforce_mode = 32;
1932 break;
1933 default:
1934 dsp_bit_width_enforce_mode = 0;
1935 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1936 break;
1937 }
1938 }
1939
1940 return dsp_bit_width_enforce_mode;
1941}
1942
1943static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1944 uint32_t enforce_mode,
1945 bool enable)
1946{
1947 struct mixer_ctl *ctl = NULL;
1948 const char *mixer_ctl_name = "ASM Bit Width";
1949 uint32_t asm_bit_width_mode = 0;
1950
1951 if (enforce_mode == 0) {
1952 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1953 return;
1954 }
1955
1956 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1957 if (!ctl) {
1958 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1959 __func__, mixer_ctl_name);
1960 return;
1961 }
1962
1963 if (enable)
1964 asm_bit_width_mode = enforce_mode;
1965 else
1966 asm_bit_width_mode = 0;
1967
1968 ALOGV("%s DSP bit width feature status is %d width=%d",
1969 __func__, enable, asm_bit_width_mode);
1970 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1971 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1972 asm_bit_width_mode);
1973
1974 return;
1975}
1976
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301977/*
1978 * if native DSD playback active
1979 */
1980bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1981{
1982 bool active = false;
1983 struct listnode *node = NULL;
1984 struct audio_usecase *uc = NULL;
1985 struct stream_out *curr_out = NULL;
1986
1987 list_for_each(node, &adev->usecase_list) {
1988 uc = node_to_item(node, struct audio_usecase, list);
1989 curr_out = (struct stream_out*) uc->stream.out;
1990
1991 if (curr_out && PCM_PLAYBACK == uc->type &&
1992 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1993 active = true;
1994 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301995 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301996 }
1997 }
1998 return active;
1999}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302000
2001static bool force_device_switch(struct audio_usecase *usecase)
2002{
2003 bool ret = false;
2004 bool is_it_true_mode = false;
2005
Zhou Song30f2c3e2018-02-08 14:02:15 +08002006 if (usecase->type == PCM_CAPTURE ||
2007 usecase->type == TRANSCODE_LOOPBACK) {
2008 return false;
2009 }
2010
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002011 if(usecase->stream.out == NULL) {
2012 ALOGE("%s: stream.out is NULL", __func__);
2013 return false;
2014 }
2015
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302016 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002017 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2018 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2019 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302020 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2021 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2022 (!is_it_true_mode && adev->native_playback_enabled)){
2023 ret = true;
2024 ALOGD("napb: time to toggle native mode");
2025 }
2026 }
2027
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302028 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302029 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2030 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002031 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302032 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302033 ALOGD("Force a2dp device switch to update new encoder config");
2034 ret = true;
2035 }
2036
Manish Dewangan671a4202017-08-18 17:30:46 +05302037 if (usecase->stream.out->stream_config_changed) {
2038 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2039 return true;
2040 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302041 return ret;
2042}
2043
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302044bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2045{
2046 bool ret=false;
2047 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2048 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2049 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2050 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2051 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2052 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2053 ret = true;
2054
2055 return ret;
2056}
2057
2058bool is_a2dp_device(snd_device_t out_snd_device)
2059{
2060 bool ret=false;
2061 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2062 ret = true;
2063
2064 return ret;
2065}
2066
2067bool is_bt_soc_on(struct audio_device *adev)
2068{
2069 struct mixer_ctl *ctl;
2070 char *mixer_ctl_name = "BT SOC status";
2071 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2072 bool bt_soc_status = true;
2073 if (!ctl) {
2074 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2075 __func__, mixer_ctl_name);
2076 /*This is to ensure we dont break targets which dont have the kernel change*/
2077 return true;
2078 }
2079 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2080 ALOGD("BT SOC status: %d",bt_soc_status);
2081 return bt_soc_status;
2082}
2083
2084int out_standby_l(struct audio_stream *stream);
2085
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002086int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002087{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002088 snd_device_t out_snd_device = SND_DEVICE_NONE;
2089 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002090 struct audio_usecase *usecase = NULL;
2091 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002092 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002093 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302094 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002095 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002096 int status = 0;
Weiyin Jiang5d608082018-02-01 17:24:33 +08002097 audio_devices_t audio_device;
2098 audio_channel_mask_t channel_mask;
2099 int sample_rate;
2100 int acdb_id;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302102 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2103
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002104 usecase = get_usecase_from_list(adev, uc_id);
2105 if (usecase == NULL) {
2106 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2107 return -EINVAL;
2108 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002110 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002111 (usecase->type == VOIP_CALL) ||
2112 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302113 if(usecase->stream.out == NULL) {
2114 ALOGE("%s: stream.out is NULL", __func__);
2115 return -EINVAL;
2116 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002117 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002118 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002119 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002120 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302121 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
2122 if (usecase->stream.inout == NULL) {
2123 ALOGE("%s: stream.inout is NULL", __func__);
2124 return -EINVAL;
2125 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302126 stream_out.devices = usecase->stream.inout->out_config.devices;
2127 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2128 stream_out.format = usecase->stream.inout->out_config.format;
2129 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2130 out_snd_device = platform_get_output_snd_device(adev->platform,
2131 &stream_out);
2132 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302133 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002134 } else {
2135 /*
2136 * If the voice call is active, use the sound devices of voice call usecase
2137 * so that it would not result any device switch. All the usecases will
2138 * be switched to new device when select_devices() is called for voice call
2139 * usecase. This is to avoid switching devices for voice call when
2140 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002141 * choose voice call device only if the use case device is
2142 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002143 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002144 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002145 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002146 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002147 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2148 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302149 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2150 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002151 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002152 in_snd_device = vc_usecase->in_snd_device;
2153 out_snd_device = vc_usecase->out_snd_device;
2154 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002155 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002156 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002157 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002158 if ((voip_usecase != NULL) &&
2159 (usecase->type == PCM_PLAYBACK) &&
2160 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002161 out_snd_device_backend_match = platform_check_backends_match(
2162 voip_usecase->out_snd_device,
2163 platform_get_output_snd_device(
2164 adev->platform,
2165 usecase->stream.out));
2166 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002167 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002168 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2169 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002170 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002171 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002172 in_snd_device = voip_usecase->in_snd_device;
2173 out_snd_device = voip_usecase->out_snd_device;
2174 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002175 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002176 hfp_ucid = audio_extn_hfp_get_usecase();
2177 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002178 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002179 in_snd_device = hfp_usecase->in_snd_device;
2180 out_snd_device = hfp_usecase->out_snd_device;
2181 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002182 }
2183 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302184 if (usecase->stream.out == NULL) {
2185 ALOGE("%s: stream.out is NULL", __func__);
2186 return -EINVAL;
2187 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002188 usecase->devices = usecase->stream.out->devices;
2189 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002190 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002191 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002192 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002193 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleiz3ca773f2018-10-12 15:49:35 +08002194 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002195 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2196
2197 if ((usecase->stream.out != NULL &&
2198 voip_usecase != NULL &&
2199 usecase->stream.out->usecase == voip_usecase->id) &&
2200 adev->active_input &&
kunleiz3ca773f2018-10-12 15:49:35 +08002201 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002202 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002203 select_devices(adev, adev->active_input->usecase);
2204 }
2205 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002206 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302207 if (usecase->stream.in == NULL) {
2208 ALOGE("%s: stream.in is NULL", __func__);
2209 return -EINVAL;
2210 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002211 usecase->devices = usecase->stream.in->device;
2212 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002213 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002214 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002215 if (adev->active_input &&
2216 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302217 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002218 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2219 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2220 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2221 out_device = voip_usecase->stream.out->devices;
2222 else if (adev->primary_output && !adev->primary_output->standby)
2223 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002224 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002225 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2226 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002227 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002228 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002229 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002230 }
2231 }
2232
2233 if (out_snd_device == usecase->out_snd_device &&
2234 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302235
2236 if (!force_device_switch(usecase))
2237 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238 }
2239
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302240 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
2241 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
2242 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2243 return 0;
2244 }
2245
sangwoobc677242013-08-08 16:53:43 +09002246 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07002247 out_snd_device, platform_get_snd_device_name(out_snd_device),
2248 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002249
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250 /*
2251 * Limitation: While in call, to do a device switch we need to disable
2252 * and enable both RX and TX devices though one of them is same as current
2253 * device.
2254 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002255 if ((usecase->type == VOICE_CALL) &&
2256 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2257 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002258 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002259 }
2260
2261 if (((usecase->type == VOICE_CALL) ||
2262 (usecase->type == VOIP_CALL)) &&
2263 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2264 /* Disable sidetone only if voice/voip call already exists */
2265 if (voice_is_call_state_active(adev) ||
2266 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002267 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002268
2269 /* Disable aanc only if voice call exists */
2270 if (voice_is_call_state_active(adev))
2271 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002272 }
2273
Zhou Songc66eb7e2017-08-08 18:29:07 +08002274 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302275 (!audio_extn_a2dp_is_ready())) {
2276 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002277 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302278 }
2279
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002280 /* Disable current sound devices */
2281 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002282 disable_audio_route(adev, usecase);
2283 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002284 }
2285
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002286 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002287 disable_audio_route(adev, usecase);
2288 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002289 }
2290
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002291 /* Applicable only on the targets that has external modem.
2292 * New device information should be sent to modem before enabling
2293 * the devices to reduce in-call device switch time.
2294 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002295 if ((usecase->type == VOICE_CALL) &&
2296 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2297 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002298 status = platform_switch_voice_call_enable_device_config(adev->platform,
2299 out_snd_device,
2300 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002301 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002302
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002303 /* Enable new sound devices */
2304 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002305 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302306 if (platform_check_codec_asrc_support(adev->platform))
2307 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002308 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002309 }
2310
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002311 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302312 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002313 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002314 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002315
Avinash Vaish71a8b972014-07-24 15:36:33 +05302316 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002317 status = platform_switch_voice_call_device_post(adev->platform,
2318 out_snd_device,
2319 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302320 enable_audio_route_for_voice_usecases(adev, usecase);
2321 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002322
sangwoo170731f2013-06-08 15:36:36 +09002323 usecase->in_snd_device = in_snd_device;
2324 usecase->out_snd_device = out_snd_device;
2325
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302326 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2327 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302328 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002329 if ((24 == usecase->stream.out->bit_width) &&
2330 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2331 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2332 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2333 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2334 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2335 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2336 /*
2337 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2338 * configured device sample rate, if not update the COPP rate to be equal to the
2339 * device sample rate, else open COPP at stream sample rate
2340 */
2341 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2342 usecase->stream.out->sample_rate,
2343 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302344 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2345 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002346 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2347 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2348 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2349 }
2350
Weiyin Jiang5d608082018-02-01 17:24:33 +08002351 /* Cache stream information to be notified to gef clients */
2352 audio_device = usecase->stream.out->devices;
2353 channel_mask = usecase->stream.out->channel_mask;
2354 sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
2355 acdb_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302356 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002357 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002358
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002359 /* If input stream is already running then effect needs to be
2360 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002361 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2362 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002363 check_and_enable_effect(adev);
2364
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002365 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002366 /* Enable aanc only if voice call exists */
2367 if (voice_is_call_state_active(adev))
2368 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2369
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002370 /* Enable sidetone only if other voice/voip call already exists */
2371 if (voice_is_call_state_active(adev) ||
2372 voice_extn_compress_voip_is_started(adev))
2373 voice_set_sidetone(adev, out_snd_device, true);
2374 }
2375
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002376 /* Applicable only on the targets that has external modem.
2377 * Enable device command should be sent to modem only after
2378 * enabling voice call mixer controls
2379 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002380 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002381 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2382 out_snd_device,
2383 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302384
2385 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2386
2387 if (usecase->type == VOIP_CALL) {
2388 if (adev->active_input != NULL &&
2389 !adev->active_input->standby) {
2390 if (is_bt_soc_on(adev) == false){
2391 ALOGD("BT SCO MIC disconnected while in connection");
2392 if (adev->active_input->pcm != NULL)
2393 pcm_stop(adev->active_input->pcm);
2394 }
2395 }
2396 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2397 && usecase->stream.out->started) {
2398 if (is_bt_soc_on(adev) == false) {
2399 ALOGD("BT SCO/A2DP disconnected while in connection");
2400 out_standby_l(&usecase->stream.out->stream.common);
2401 }
2402 }
2403 } else if ((usecase->stream.out != NULL) &&
2404 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2405 usecase->stream.out->started) {
2406 if (is_bt_soc_on(adev) == false) {
2407 ALOGD("BT SCO/A2dp disconnected while in connection");
2408 out_standby_l(&usecase->stream.out->stream.common);
2409 }
2410 }
2411 }
2412
Weiyin Jiang5d608082018-02-01 17:24:33 +08002413 /* Notify device change info to effect clients registered
2414 * NOTE: device lock has to be unlock temporarily here.
2415 * To the worst case, we notify stale info to clients.
2416 */
2417 if (usecase->type == PCM_PLAYBACK) {
2418 pthread_mutex_unlock(&adev->lock);
2419 audio_extn_gef_notify_device_config(audio_device, channel_mask, sample_rate, acdb_id);
2420 pthread_mutex_lock(&adev->lock);
2421 }
2422
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302423 ALOGD("%s: done",__func__);
2424
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425 return status;
2426}
2427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002428static int stop_input_stream(struct stream_in *in)
2429{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302430 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002431 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302432
2433 if (in == NULL) {
2434 ALOGE("%s: stream_in ptr is NULL", __func__);
2435 return -EINVAL;
2436 }
2437
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438 struct audio_device *adev = in->dev;
2439
Eric Laurent994a6932013-07-17 11:51:42 -07002440 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002441 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002442 uc_info = get_usecase_from_list(adev, in->usecase);
2443 if (uc_info == NULL) {
2444 ALOGE("%s: Could not find the usecase (%d) in the list",
2445 __func__, in->usecase);
2446 return -EINVAL;
2447 }
2448
Derek Chencdd17c72014-11-24 12:39:14 -08002449 if (uc_info->in_snd_device != SND_DEVICE_NONE) {
2450 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2451 ALOGE("%s: failed to stop ext hw plugin", __func__);
2452 }
2453
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002454 /* Close in-call recording streams */
2455 voice_check_and_stop_incall_rec_usecase(adev, in);
2456
Eric Laurent150dbfe2013-02-27 14:31:02 -08002457 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002458 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002459
2460 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002461 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002463 list_remove(&uc_info->list);
2464 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002466 adev->active_input = get_next_active_input(adev);
Vatsal Buchaa1358992018-11-14 13:25:08 +05302467 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002468 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469 return ret;
2470}
2471
2472int start_input_stream(struct stream_in *in)
2473{
2474 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002475 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302477
2478 if (in == NULL) {
2479 ALOGE("%s: stream_in ptr is NULL", __func__);
2480 return -EINVAL;
2481 }
2482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002484 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002485 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486
Mingming Yin2664a5b2015-09-03 10:53:11 -07002487 if (get_usecase_from_list(adev, usecase) == NULL)
2488 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302489 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2490 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002491
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302492 if (CARD_STATUS_OFFLINE == in->card_status||
2493 CARD_STATUS_OFFLINE == adev->card_status) {
2494 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302495 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302496 goto error_config;
2497 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302498
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302499 if (audio_is_bluetooth_sco_device(in->device)) {
2500 if (!adev->bt_sco_on) {
2501 ALOGE("%s: SCO profile is not ready, return error", __func__);
2502 ret = -EIO;
2503 goto error_config;
2504 }
2505 }
2506
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002507 /* Check if source matches incall recording usecase criteria */
2508 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2509 if (ret)
2510 goto error_config;
2511 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002512 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2513
2514 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2515 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2516 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002517 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002518 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002519
Eric Laurentb23d5282013-05-14 15:27:20 -07002520 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521 if (in->pcm_device_id < 0) {
2522 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2523 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002524 ret = -EINVAL;
2525 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002527
2528 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002530
2531 if (!uc_info) {
2532 ret = -ENOMEM;
2533 goto error_config;
2534 }
2535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536 uc_info->id = in->usecase;
2537 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002538 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002539 uc_info->devices = in->device;
2540 uc_info->in_snd_device = SND_DEVICE_NONE;
2541 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002543 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302544 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2545 adev->perf_lock_opts,
2546 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002547 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548
Derek Chencdd17c72014-11-24 12:39:14 -08002549 if (uc_info->in_snd_device != SND_DEVICE_NONE) {
2550 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2551 ALOGE("%s: failed to start ext hw plugin", __func__);
2552 }
2553
Haynes Mathew George16081042017-05-31 17:16:49 -07002554 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302555 ret = audio_extn_cin_start_input_stream(in);
2556 if (ret)
2557 goto error_open;
2558 else
2559 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002560 }
2561
Haynes Mathew George16081042017-05-31 17:16:49 -07002562 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002563 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002564 ALOGE("%s: pcm stream not ready", __func__);
2565 goto error_open;
2566 }
2567 ret = pcm_start(in->pcm);
2568 if (ret < 0) {
2569 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2570 goto error_open;
2571 }
2572 } else {
2573 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2574 unsigned int pcm_open_retry_count = 0;
2575
2576 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2577 flags |= PCM_MMAP | PCM_NOIRQ;
2578 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2579 } else if (in->realtime) {
2580 flags |= PCM_MMAP | PCM_NOIRQ;
2581 }
2582
Garmond Leunge2433c32017-09-28 21:51:22 -07002583 if (audio_extn_ffv_get_stream() == in) {
2584 ALOGD("%s: ffv stream, update pcm config", __func__);
2585 audio_extn_ffv_update_pcm_config(&config);
2586 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002587 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2588 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2589
2590 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002591 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002592 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002593 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002594 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05302595 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
2596 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2597 adev->card_status = CARD_STATUS_OFFLINE;
2598 in->card_status = CARD_STATUS_OFFLINE;
2599 ret = -EIO;
2600 goto error_open;
2601 }
2602
Haynes Mathew George16081042017-05-31 17:16:49 -07002603 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2604 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2605 if (in->pcm != NULL) {
2606 pcm_close(in->pcm);
2607 in->pcm = NULL;
2608 }
2609 if (pcm_open_retry_count-- == 0) {
2610 ret = -EIO;
2611 goto error_open;
2612 }
2613 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2614 continue;
2615 }
2616 break;
2617 }
2618
2619 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002620 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002621 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002622 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002623 if (ret < 0) {
2624 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2625 pcm_close(in->pcm);
2626 in->pcm = NULL;
2627 goto error_open;
2628 }
2629 register_in_stream(in);
2630 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002631 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002632 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002633 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002634 if (ret < 0) {
2635 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002636 pcm_close(in->pcm);
2637 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002638 goto error_open;
2639 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002640 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002641 }
2642
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002643 check_and_enable_effect(adev);
2644
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302645done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302646 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002647 ALOGD("%s: exit", __func__);
Vatsal Buchaa1358992018-11-14 13:25:08 +05302648 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002649 return ret;
2650
2651error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302652 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002654error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302655 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302656 /*
2657 * sleep 50ms to allow sufficient time for kernel
2658 * drivers to recover incases like SSR.
2659 */
2660 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002661 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchaa1358992018-11-14 13:25:08 +05302662 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002663 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664}
2665
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002666void lock_input_stream(struct stream_in *in)
2667{
2668 pthread_mutex_lock(&in->pre_lock);
2669 pthread_mutex_lock(&in->lock);
2670 pthread_mutex_unlock(&in->pre_lock);
2671}
2672
2673void lock_output_stream(struct stream_out *out)
2674{
2675 pthread_mutex_lock(&out->pre_lock);
2676 pthread_mutex_lock(&out->lock);
2677 pthread_mutex_unlock(&out->pre_lock);
2678}
2679
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002680/* must be called with out->lock locked */
2681static int send_offload_cmd_l(struct stream_out* out, int command)
2682{
2683 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2684
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002685 if (!cmd) {
2686 ALOGE("failed to allocate mem for command 0x%x", command);
2687 return -ENOMEM;
2688 }
2689
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002690 ALOGVV("%s %d", __func__, command);
2691
2692 cmd->cmd = command;
2693 list_add_tail(&out->offload_cmd_list, &cmd->node);
2694 pthread_cond_signal(&out->offload_cond);
2695 return 0;
2696}
2697
2698/* must be called iwth out->lock locked */
2699static void stop_compressed_output_l(struct stream_out *out)
2700{
2701 out->offload_state = OFFLOAD_STATE_IDLE;
2702 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002703 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002704 if (out->compr != NULL) {
2705 compress_stop(out->compr);
2706 while (out->offload_thread_blocked) {
2707 pthread_cond_wait(&out->cond, &out->lock);
2708 }
2709 }
2710}
2711
Varun Balaraje49253e2017-07-06 19:48:56 +05302712bool is_interactive_usecase(audio_usecase_t uc_id)
2713{
2714 unsigned int i;
2715 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2716 if (uc_id == interactive_usecases[i])
2717 return true;
2718 }
2719 return false;
2720}
2721
2722static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2723{
2724 audio_usecase_t ret_uc = USECASE_INVALID;
2725 unsigned int intract_uc_index;
2726 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2727
2728 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2729 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2730 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2731 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2732 ret_uc = interactive_usecases[intract_uc_index];
2733 break;
2734 }
2735 }
2736
2737 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2738 return ret_uc;
2739}
2740
2741static void free_interactive_usecase(struct audio_device *adev,
2742 audio_usecase_t uc_id)
2743{
2744 unsigned int interact_uc_index;
2745 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2746
2747 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2748 if (interactive_usecases[interact_uc_index] == uc_id) {
2749 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2750 break;
2751 }
2752 }
2753 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2754}
2755
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002756bool is_offload_usecase(audio_usecase_t uc_id)
2757{
2758 unsigned int i;
2759 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2760 if (uc_id == offload_usecases[i])
2761 return true;
2762 }
2763 return false;
2764}
2765
Dhananjay Kumarac341582017-02-23 23:42:25 +05302766static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002767{
vivek mehta446c3962015-09-14 10:57:35 -07002768 audio_usecase_t ret_uc = USECASE_INVALID;
2769 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002770 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002771 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302772 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002773 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2774 else
2775 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002776
vivek mehta446c3962015-09-14 10:57:35 -07002777 pthread_mutex_lock(&adev->lock);
2778 if (get_usecase_from_list(adev, ret_uc) != NULL)
2779 ret_uc = USECASE_INVALID;
2780 pthread_mutex_unlock(&adev->lock);
2781
2782 return ret_uc;
2783 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002784
2785 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002786 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2787 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2788 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2789 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002790 break;
2791 }
2792 }
vivek mehta446c3962015-09-14 10:57:35 -07002793
2794 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2795 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002796}
2797
2798static void free_offload_usecase(struct audio_device *adev,
2799 audio_usecase_t uc_id)
2800{
vivek mehta446c3962015-09-14 10:57:35 -07002801 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002802 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002803
2804 if (!adev->multi_offload_enable)
2805 return;
2806
2807 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2808 if (offload_usecases[offload_uc_index] == uc_id) {
2809 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002810 break;
2811 }
2812 }
2813 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2814}
2815
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002816static void *offload_thread_loop(void *context)
2817{
2818 struct stream_out *out = (struct stream_out *) context;
2819 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002820 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002821
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002822 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2823 set_sched_policy(0, SP_FOREGROUND);
2824 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2825
2826 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002827 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002828 for (;;) {
2829 struct offload_cmd *cmd = NULL;
2830 stream_callback_event_t event;
2831 bool send_callback = false;
2832
2833 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2834 __func__, list_empty(&out->offload_cmd_list),
2835 out->offload_state);
2836 if (list_empty(&out->offload_cmd_list)) {
2837 ALOGV("%s SLEEPING", __func__);
2838 pthread_cond_wait(&out->offload_cond, &out->lock);
2839 ALOGV("%s RUNNING", __func__);
2840 continue;
2841 }
2842
2843 item = list_head(&out->offload_cmd_list);
2844 cmd = node_to_item(item, struct offload_cmd, node);
2845 list_remove(item);
2846
2847 ALOGVV("%s STATE %d CMD %d out->compr %p",
2848 __func__, out->offload_state, cmd->cmd, out->compr);
2849
2850 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2851 free(cmd);
2852 break;
2853 }
2854
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002855 // allow OFFLOAD_CMD_ERROR reporting during standby
2856 // this is needed to handle failures during compress_open
2857 // Note however that on a pause timeout, the stream is closed
2858 // and no offload usecase will be active. Therefore this
2859 // special case is needed for compress_open failures alone
2860 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2861 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002862 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002863 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002864 pthread_cond_signal(&out->cond);
2865 continue;
2866 }
2867 out->offload_thread_blocked = true;
2868 pthread_mutex_unlock(&out->lock);
2869 send_callback = false;
2870 switch(cmd->cmd) {
2871 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002872 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002873 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002874 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002875 send_callback = true;
2876 event = STREAM_CBK_EVENT_WRITE_READY;
2877 break;
2878 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002879 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302880 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002881 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302882 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002883 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302884 if (ret < 0)
2885 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302886 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302887 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002888 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002889 else
2890 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002891 if (-ENETRESET != ret && !(-EINTR == ret &&
2892 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302893 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302894 pthread_mutex_lock(&out->lock);
2895 out->send_new_metadata = 1;
2896 out->send_next_track_params = true;
2897 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302898 event = STREAM_CBK_EVENT_DRAIN_READY;
2899 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2900 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302901 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002902 break;
2903 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002904 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002905 ret = compress_drain(out->compr);
2906 ALOGD("copl(%p):out of compress_drain", out);
2907 // EINTR check avoids drain interruption due to SSR
2908 if (-ENETRESET != ret && !(-EINTR == ret &&
2909 CARD_STATUS_OFFLINE == out->card_status)) {
2910 send_callback = true;
2911 event = STREAM_CBK_EVENT_DRAIN_READY;
2912 } else
2913 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002914 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302915 case OFFLOAD_CMD_ERROR:
2916 ALOGD("copl(%p): sending error callback to AF", out);
2917 send_callback = true;
2918 event = STREAM_CBK_EVENT_ERROR;
2919 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002920 default:
2921 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2922 break;
2923 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002924 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002925 out->offload_thread_blocked = false;
2926 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002927 if (send_callback && out->client_callback) {
2928 ALOGVV("%s: sending client_callback event %d", __func__, event);
2929 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002930 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002931 free(cmd);
2932 }
2933
2934 pthread_cond_signal(&out->cond);
2935 while (!list_empty(&out->offload_cmd_list)) {
2936 item = list_head(&out->offload_cmd_list);
2937 list_remove(item);
2938 free(node_to_item(item, struct offload_cmd, node));
2939 }
2940 pthread_mutex_unlock(&out->lock);
2941
2942 return NULL;
2943}
2944
2945static int create_offload_callback_thread(struct stream_out *out)
2946{
2947 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2948 list_init(&out->offload_cmd_list);
2949 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2950 offload_thread_loop, out);
2951 return 0;
2952}
2953
2954static int destroy_offload_callback_thread(struct stream_out *out)
2955{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002956 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002957 stop_compressed_output_l(out);
2958 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2959
2960 pthread_mutex_unlock(&out->lock);
2961 pthread_join(out->offload_thread, (void **) NULL);
2962 pthread_cond_destroy(&out->offload_cond);
2963
2964 return 0;
2965}
2966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002967static int stop_output_stream(struct stream_out *out)
2968{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302969 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002970 struct audio_usecase *uc_info;
2971 struct audio_device *adev = out->dev;
2972
Eric Laurent994a6932013-07-17 11:51:42 -07002973 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002974 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002975 uc_info = get_usecase_from_list(adev, out->usecase);
2976 if (uc_info == NULL) {
2977 ALOGE("%s: Could not find the usecase (%d) in the list",
2978 __func__, out->usecase);
2979 return -EINVAL;
2980 }
2981
Derek Chencdd17c72014-11-24 12:39:14 -08002982 if (uc_info->out_snd_device != SND_DEVICE_NONE) {
2983 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2984 ALOGE("%s: failed to stop ext hw plugin", __func__);
2985 }
2986
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002987 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302988 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002989 if (adev->visualizer_stop_output != NULL)
2990 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002991
2992 audio_extn_dts_remove_state_notifier_node(out->usecase);
2993
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002994 if (adev->offload_effects_stop_output != NULL)
2995 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2996 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002997
Arun Mirpuridbef0c72018-09-12 18:36:10 -07002998 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
2999 out->usecase == USECASE_INCALL_MUSIC_UPLINK2)
Arun Mirpurief53ce52018-09-11 18:00:09 -07003000 voice_set_device_mute_flag(adev, false);
3001
Eric Laurent150dbfe2013-02-27 14:31:02 -08003002 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003003 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003004
3005 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003006 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003008 if (is_offload_usecase(out->usecase)) {
3009 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3010 adev->dsp_bit_width_enforce_mode,
3011 false);
3012 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003013 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3014 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3015 false);
3016
3017 if (ret != 0)
3018 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3019 /* default service interval was successfully updated,
3020 reopen USB backend with new service interval */
3021 ret = 0;
3022 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003023
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003024 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303025 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003026 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303027 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003028 ALOGV("Disable passthrough , reset mixer to pcm");
3029 /* NO_PASSTHROUGH */
3030 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003031 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003032 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3033 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003034
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303035 /* Must be called after removing the usecase from list */
3036 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303037 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303038
Manish Dewangan21a850a2017-08-14 12:03:55 +05303039 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003040 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3041 if (ret < 0)
3042 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3043 }
3044
Garmond Leung5fd0b552018-04-17 11:56:12 -07003045 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003046 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047 return ret;
3048}
3049
3050int start_output_stream(struct stream_out *out)
3051{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053 struct audio_usecase *uc_info;
3054 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003055 char mixer_ctl_name[128];
3056 struct mixer_ctl *ctl = NULL;
3057 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303058 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059
Haynes Mathew George380745d2017-10-04 15:27:45 -07003060 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003061 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3062 ret = -EINVAL;
3063 goto error_config;
3064 }
3065
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303066 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
3067 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
3068 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303069
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303070 if (CARD_STATUS_OFFLINE == out->card_status ||
3071 CARD_STATUS_OFFLINE == adev->card_status) {
3072 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303073 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303074 goto error_config;
3075 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303076
Arun Mirpuridbef0c72018-09-12 18:36:10 -07003077 //Update incall music usecase to reflect correct voice session
3078 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3079 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3080 if (ret != 0) {
3081 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3082 __func__, ret);
3083 goto error_config;
3084 }
3085 }
3086
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303087 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
3088 if (!audio_extn_a2dp_is_ready()) {
3089 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303090 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303091 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303092 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3093 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3094 ret = -EAGAIN;
3095 goto error_config;
3096 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303097 }
3098 }
3099 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303100 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3101 if (!adev->bt_sco_on) {
3102 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3103 //combo usecase just by pass a2dp
3104 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3105 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3106 } else {
3107 ALOGE("%s: SCO profile is not ready, return error", __func__);
3108 ret = -EAGAIN;
3109 goto error_config;
3110 }
3111 }
3112 }
3113
Eric Laurentb23d5282013-05-14 15:27:20 -07003114 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003115 if (out->pcm_device_id < 0) {
3116 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3117 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003118 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003119 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120 }
3121
3122 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003123
3124 if (!uc_info) {
3125 ret = -ENOMEM;
3126 goto error_config;
3127 }
3128
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003129 uc_info->id = out->usecase;
3130 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003131 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003132 uc_info->devices = out->devices;
3133 uc_info->in_snd_device = SND_DEVICE_NONE;
3134 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003135
3136 /* This must be called before adding this usecase to the list */
3137 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3138 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3139 /* USB backend is not reopened immediately.
3140 This is eventually done as part of select_devices */
3141 }
3142
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003143 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303145 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3146 adev->perf_lock_opts,
3147 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303148
3149 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303150 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303151 if (audio_extn_passthru_is_enabled() &&
3152 audio_extn_passthru_is_passthrough_stream(out)) {
3153 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303154 }
3155 }
3156
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303157 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3158 (!audio_extn_a2dp_is_ready())) {
3159 if (!a2dp_combo) {
3160 check_a2dp_restore_l(adev, out, false);
3161 } else {
3162 audio_devices_t dev = out->devices;
3163 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3164 select_devices(adev, out->usecase);
3165 out->devices = dev;
3166 }
3167 } else {
3168 select_devices(adev, out->usecase);
3169 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003170
Arun Mirpuridbef0c72018-09-12 18:36:10 -07003171 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3172 out->usecase == USECASE_INCALL_MUSIC_UPLINK2)
Arun Mirpurief53ce52018-09-11 18:00:09 -07003173 voice_set_device_mute_flag(adev, true);
3174
Derek Chencdd17c72014-11-24 12:39:14 -08003175 if (uc_info->out_snd_device != SND_DEVICE_NONE) {
3176 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3177 ALOGE("%s: failed to start ext hw plugin", __func__);
3178 }
3179
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003180 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3181 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003182
3183 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuriebe78a72018-10-04 18:23:46 -07003184 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003185 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3186 ALOGE("%s: pcm stream not ready", __func__);
3187 goto error_open;
3188 }
3189 ret = pcm_start(out->pcm);
3190 if (ret < 0) {
3191 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3192 goto error_open;
3193 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07003194 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003195 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003196 unsigned int flags = PCM_OUT;
3197 unsigned int pcm_open_retry_count = 0;
3198 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3199 flags |= PCM_MMAP | PCM_NOIRQ;
3200 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003201 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003202 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003203 } else
3204 flags |= PCM_MONOTONIC;
3205
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003206 if ((adev->vr_audio_mode_enabled) &&
3207 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3208 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3209 "PCM_Dev %d Topology", out->pcm_device_id);
3210 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3211 if (!ctl) {
3212 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3213 __func__, mixer_ctl_name);
3214 } else {
3215 //if success use ULLPP
3216 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3217 __func__, mixer_ctl_name, out->pcm_device_id);
3218 //There is a still a possibility that some sessions
3219 // that request for FAST|RAW when 3D audio is active
3220 //can go through ULLPP. Ideally we expects apps to
3221 //listen to audio focus and stop concurrent playback
3222 //Also, we will look for mode flag (voice_in_communication)
3223 //before enabling the realtime flag.
3224 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3225 }
3226 }
3227
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003228 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003229 ATRACE_BEGIN("pcm_open");
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003230 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3231 flags, &out->config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003232 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05303233 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
3234 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3235 out->card_status = CARD_STATUS_OFFLINE;
3236 adev->card_status = CARD_STATUS_OFFLINE;
3237 ret = -EIO;
3238 goto error_open;
3239 }
3240
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003241 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3242 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3243 if (out->pcm != NULL) {
3244 pcm_close(out->pcm);
3245 out->pcm = NULL;
3246 }
3247 if (pcm_open_retry_count-- == 0) {
3248 ret = -EIO;
3249 goto error_open;
3250 }
3251 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3252 continue;
3253 }
3254 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003255 }
Surendar Karka5a18a7a2018-04-26 11:28:38 +05303256 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3257 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003258
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003259 ALOGV("%s: pcm_prepare", __func__);
3260 if (pcm_is_ready(out->pcm)) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003261 ATRACE_BEGIN("pcm_prepare");
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003262 ret = pcm_prepare(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003263 ATRACE_END();
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003264 if (ret < 0) {
3265 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3266 pcm_close(out->pcm);
3267 out->pcm = NULL;
3268 goto error_open;
3269 }
3270 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08003271 // apply volume for voip playback after path is set up
3272 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3273 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003274 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003275 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303276 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003277 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3278 adev->dsp_bit_width_enforce_mode,
3279 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003280 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003281 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003282 out->compr = compress_open(adev->snd_card,
3283 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003284 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003285 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05303286 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
3287 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3288 adev->card_status = CARD_STATUS_OFFLINE;
3289 out->card_status = CARD_STATUS_OFFLINE;
3290 ret = -EIO;
3291 goto error_open;
3292 }
3293
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003294 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003295 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003296 compress_close(out->compr);
3297 out->compr = NULL;
3298 ret = -EIO;
3299 goto error_open;
3300 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303301 /* compress_open sends params of the track, so reset the flag here */
3302 out->is_compr_metadata_avail = false;
3303
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003304 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003305 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003306
Fred Oh3f43e742015-03-04 18:42:34 -08003307 /* Since small bufs uses blocking writes, a write will be blocked
3308 for the default max poll time (20s) in the event of an SSR.
3309 Reduce the poll time to observe and deal with SSR faster.
3310 */
Ashish Jain5106d362016-05-11 19:23:33 +05303311 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003312 compress_set_max_poll_wait(out->compr, 1000);
3313 }
3314
Manish Dewangan69426c82017-01-30 17:35:36 +05303315 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303316 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303317
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003318 audio_extn_dts_create_state_notifier_node(out->usecase);
3319 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3320 popcount(out->channel_mask),
3321 out->playback_started);
3322
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003323#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303324 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003325 audio_extn_dolby_send_ddp_endp_params(adev);
3326#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303327 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3328 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003329 if (adev->visualizer_start_output != NULL)
3330 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3331 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303332 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003333 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003334 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003335 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003336
3337 if (ret == 0) {
3338 register_out_stream(out);
3339 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003340 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3341 ALOGE("%s: pcm stream not ready", __func__);
3342 goto error_open;
3343 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003344 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003345 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003346 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003347 if (ret < 0)
3348 goto error_open;
3349 }
3350 }
3351
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303352 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003353 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003354
Manish Dewangan21a850a2017-08-14 12:03:55 +05303355 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003356 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003357 if (ret < 0)
3358 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3359 }
3360
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003361 // consider a scenario where on pause lower layers are tear down.
3362 // so on resume, swap mixer control need to be sent only when
3363 // backend is active, hence rather than sending from enable device
3364 // sending it from start of streamtream
3365
3366 platform_set_swap_channels(adev, true);
3367
Haynes Mathew George380745d2017-10-04 15:27:45 -07003368 ATRACE_END();
Vatsal Buchaa1358992018-11-14 13:25:08 +05303369 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003370 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003371error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303372 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003374error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303375 /*
3376 * sleep 50ms to allow sufficient time for kernel
3377 * drivers to recover incases like SSR.
3378 */
3379 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003380 ATRACE_END();
Vatsal Buchaa1358992018-11-14 13:25:08 +05303381 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003382 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003383}
3384
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385static int check_input_parameters(uint32_t sample_rate,
3386 audio_format_t format,
3387 int channel_count)
3388{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003389 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303391 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3392 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3393 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003394 !voice_extn_compress_voip_is_format_supported(format) &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003395 !audio_extn_compr_cap_format_supported(format))
3396 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003397
3398 switch (channel_count) {
3399 case 1:
3400 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303401 case 3:
3402 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003403 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003404 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003405 break;
3406 default:
3407 ret = -EINVAL;
3408 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409
3410 switch (sample_rate) {
3411 case 8000:
3412 case 11025:
3413 case 12000:
3414 case 16000:
3415 case 22050:
3416 case 24000:
3417 case 32000:
3418 case 44100:
3419 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003420 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303421 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003422 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303423 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424 break;
3425 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003426 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427 }
3428
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003429 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003430}
3431
Naresh Tanniru04f71882018-06-26 17:46:22 +05303432
3433/** Add a value in a list if not already present.
3434 * @return true if value was successfully inserted or already present,
3435 * false if the list is full and does not contain the value.
3436 */
3437static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3438 for (size_t i = 0; i < list_length; i++) {
3439 if (list[i] == value) return true; // value is already present
3440 if (list[i] == 0) { // no values in this slot
3441 list[i] = value;
3442 return true; // value inserted
3443 }
3444 }
3445 return false; // could not insert value
3446}
3447
3448/** Add channel_mask in supported_channel_masks if not already present.
3449 * @return true if channel_mask was successfully inserted or already present,
3450 * false if supported_channel_masks is full and does not contain channel_mask.
3451 */
3452static void register_channel_mask(audio_channel_mask_t channel_mask,
3453 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3454 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3455 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3456}
3457
3458/** Add format in supported_formats if not already present.
3459 * @return true if format was successfully inserted or already present,
3460 * false if supported_formats is full and does not contain format.
3461 */
3462static void register_format(audio_format_t format,
3463 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3464 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3465 "%s: stream can not declare supporting its format %x", __func__, format);
3466}
3467/** Add sample_rate in supported_sample_rates if not already present.
3468 * @return true if sample_rate was successfully inserted or already present,
3469 * false if supported_sample_rates is full and does not contain sample_rate.
3470 */
3471static void register_sample_rate(uint32_t sample_rate,
3472 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3473 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3474 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3475}
3476
Karthikeyan Mani35531922018-11-07 15:44:13 -08003477static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3478{
3479 uint32_t high = num1, low = num2, temp = 0;
3480
3481 if (!num1 || !num2)
3482 return 0;
3483
3484 if (num1 < num2) {
3485 high = num2;
3486 low = num1;
3487 }
3488
3489 while (low != 0) {
3490 temp = low;
3491 low = high % low;
3492 high = temp;
3493 }
3494 return (num1 * num2)/high;
3495}
3496
3497static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3498{
3499 uint32_t remainder = 0;
3500
3501 if (!multiplier)
3502 return num;
3503
3504 remainder = num % multiplier;
3505 if (remainder)
3506 num += (multiplier - remainder);
3507
3508 return num;
3509}
3510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511static size_t get_input_buffer_size(uint32_t sample_rate,
3512 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003513 int channel_count,
3514 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515{
3516 size_t size = 0;
Karthikeyan Mani35531922018-11-07 15:44:13 -08003517 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003519 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3520 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003521
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003522 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003523 if (is_low_latency)
3524 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303525
Karthikeyan Mani35531922018-11-07 15:44:13 -08003526 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
3527 size *= bytes_per_period_sample;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003529 /* make sure the size is multiple of 32 bytes
3530 * At 48 kHz mono 16-bit PCM:
3531 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3532 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Mani35531922018-11-07 15:44:13 -08003533 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003534 */
Karthikeyan Mani35531922018-11-07 15:44:13 -08003535 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003536
3537 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538}
3539
Ashish Jain058165c2016-09-28 23:18:48 +05303540static size_t get_output_period_size(uint32_t sample_rate,
3541 audio_format_t format,
3542 int channel_count,
3543 int duration /*in millisecs*/)
3544{
3545 size_t size = 0;
3546 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3547
3548 if ((duration == 0) || (sample_rate == 0) ||
3549 (bytes_per_sample == 0) || (channel_count == 0)) {
3550 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3551 bytes_per_sample, channel_count);
3552 return -EINVAL;
3553 }
3554
3555 size = (sample_rate *
3556 duration *
3557 bytes_per_sample *
3558 channel_count) / 1000;
3559 /*
3560 * To have same PCM samples for all channels, the buffer size requires to
3561 * be multiple of (number of channels * bytes per sample)
3562 * For writes to succeed, the buffer must be written at address which is multiple of 32
3563 */
3564 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3565
3566 return (size/(channel_count * bytes_per_sample));
3567}
3568
Zhou Song48453a02018-01-10 17:50:59 +08003569static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303570{
3571 uint64_t actual_frames_rendered = 0;
3572 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3573
3574 /* This adjustment accounts for buffering after app processor.
3575 * It is based on estimated DSP latency per use case, rather than exact.
3576 */
3577 int64_t platform_latency = platform_render_latency(out->usecase) *
3578 out->sample_rate / 1000000LL;
3579
Zhou Song48453a02018-01-10 17:50:59 +08003580 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303581 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3582 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3583 * hence only estimate.
3584 */
3585 int64_t signed_frames = out->written - kernel_buffer_size;
3586
3587 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3588
Zhou Song48453a02018-01-10 17:50:59 +08003589 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303590 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003591 if (timestamp != NULL )
3592 *timestamp = out->writeAt;
3593 } else if (timestamp != NULL) {
3594 clock_gettime(CLOCK_MONOTONIC, timestamp);
3595 }
3596 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303597
3598 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3599 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3600 (long long int)out->written, (int)kernel_buffer_size,
3601 audio_bytes_per_sample(out->compr_config.codec->format),
3602 popcount(out->channel_mask));
3603
3604 return actual_frames_rendered;
3605}
3606
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003607static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3608{
3609 struct stream_out *out = (struct stream_out *)stream;
3610
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003611 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612}
3613
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003614static int out_set_sample_rate(struct audio_stream *stream __unused,
3615 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616{
3617 return -ENOSYS;
3618}
3619
3620static size_t out_get_buffer_size(const struct audio_stream *stream)
3621{
3622 struct stream_out *out = (struct stream_out *)stream;
3623
Varun Balaraje49253e2017-07-06 19:48:56 +05303624 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303625 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303626 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303627 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3628 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3629 else
3630 return out->compr_config.fragment_size;
3631 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003632 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003633 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3634 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 +05303635 else if (is_offload_usecase(out->usecase) &&
3636 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303637 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003638
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003639 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003640 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641}
3642
3643static uint32_t out_get_channels(const struct audio_stream *stream)
3644{
3645 struct stream_out *out = (struct stream_out *)stream;
3646
3647 return out->channel_mask;
3648}
3649
3650static audio_format_t out_get_format(const struct audio_stream *stream)
3651{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003652 struct stream_out *out = (struct stream_out *)stream;
3653
3654 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655}
3656
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003657static int out_set_format(struct audio_stream *stream __unused,
3658 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659{
3660 return -ENOSYS;
3661}
3662
3663static int out_standby(struct audio_stream *stream)
3664{
3665 struct stream_out *out = (struct stream_out *)stream;
3666 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003667 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003668
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303669 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3670 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003672 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003674 if (adev->adm_deregister_stream)
3675 adev->adm_deregister_stream(adev->adm_data, out->handle);
3676
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003677 if (is_offload_usecase(out->usecase))
3678 stop_compressed_output_l(out);
3679
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003680 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003682 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3683 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303684 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003685 pthread_mutex_unlock(&adev->lock);
3686 pthread_mutex_unlock(&out->lock);
3687 ALOGD("VOIP output entered standby");
3688 return 0;
3689 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003690 if (out->pcm) {
3691 pcm_close(out->pcm);
3692 out->pcm = NULL;
3693 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003694 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3695 do_stop = out->playback_started;
3696 out->playback_started = false;
3697 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003698 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003699 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303700 out->send_next_track_params = false;
3701 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003702 out->gapless_mdata.encoder_delay = 0;
3703 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003704 if (out->compr != NULL) {
3705 compress_close(out->compr);
3706 out->compr = NULL;
3707 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003708 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003709 if (do_stop) {
3710 stop_output_stream(out);
3711 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003712 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713 }
3714 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303715 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716 return 0;
3717}
3718
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303719static int out_on_error(struct audio_stream *stream)
3720{
3721 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003722 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303723
3724 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003725 // always send CMD_ERROR for offload streams, this
3726 // is needed e.g. when SSR happens within compress_open
3727 // since the stream is active, offload_callback_thread is also active.
3728 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3729 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003730 }
3731 pthread_mutex_unlock(&out->lock);
3732
3733 status = out_standby(&out->stream.common);
3734
3735 lock_output_stream(out);
3736 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003737 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303738 }
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05303739
3740 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
3741 ALOGD("Setting previous card status if offline");
3742 out->prev_card_status_offline = true;
3743 }
3744
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303745 pthread_mutex_unlock(&out->lock);
3746
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003747 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303748}
3749
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303750/*
3751 *standby implementation without locks, assumes that the callee already
3752 *has taken adev and out lock.
3753 */
3754int out_standby_l(struct audio_stream *stream)
3755{
3756 struct stream_out *out = (struct stream_out *)stream;
3757 struct audio_device *adev = out->dev;
3758
3759 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3760 stream, out->usecase, use_case_table[out->usecase]);
3761
3762 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003763 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303764 if (adev->adm_deregister_stream)
3765 adev->adm_deregister_stream(adev->adm_data, out->handle);
3766
3767 if (is_offload_usecase(out->usecase))
3768 stop_compressed_output_l(out);
3769
3770 out->standby = true;
3771 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3772 voice_extn_compress_voip_close_output_stream(stream);
3773 out->started = 0;
3774 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003775 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303776 return 0;
3777 } else if (!is_offload_usecase(out->usecase)) {
3778 if (out->pcm) {
3779 pcm_close(out->pcm);
3780 out->pcm = NULL;
3781 }
3782 } else {
3783 ALOGD("copl(%p):standby", out);
3784 out->send_next_track_params = false;
3785 out->is_compr_metadata_avail = false;
3786 out->gapless_mdata.encoder_delay = 0;
3787 out->gapless_mdata.encoder_padding = 0;
3788 if (out->compr != NULL) {
3789 compress_close(out->compr);
3790 out->compr = NULL;
3791 }
3792 }
3793 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003794 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303795 }
3796 ALOGD("%s: exit", __func__);
3797 return 0;
3798}
3799
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003800static int out_dump(const struct audio_stream *stream __unused,
3801 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802{
3803 return 0;
3804}
3805
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003806static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3807{
3808 int ret = 0;
3809 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003810
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003811 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003812 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003813 return -EINVAL;
3814 }
3815
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303816 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003817
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003818 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3819 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303820 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003821 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003822 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3823 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303824 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003825 }
3826
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003827 ALOGV("%s new encoder delay %u and padding %u", __func__,
3828 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3829
3830 return 0;
3831}
3832
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003833static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3834{
3835 return out == adev->primary_output || out == adev->voice_tx_output;
3836}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003837
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303838// note: this call is safe only if the stream_cb is
3839// removed first in close_output_stream (as is done now).
3840static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3841{
3842 if (!stream || !parms)
3843 return;
3844
3845 struct stream_out *out = (struct stream_out *)stream;
3846 struct audio_device *adev = out->dev;
3847
3848 card_status_t status;
3849 int card;
3850 if (parse_snd_card_status(parms, &card, &status) < 0)
3851 return;
3852
3853 pthread_mutex_lock(&adev->lock);
3854 bool valid_cb = (card == adev->snd_card);
3855 pthread_mutex_unlock(&adev->lock);
3856
3857 if (!valid_cb)
3858 return;
3859
3860 lock_output_stream(out);
3861 if (out->card_status != status)
3862 out->card_status = status;
3863 pthread_mutex_unlock(&out->lock);
3864
3865 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3866 use_case_table[out->usecase],
3867 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3868
Aditya Bavanari9aa0b922019-02-05 17:44:57 +05303869 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303870 out_on_error(stream);
Aditya Bavanari9aa0b922019-02-05 17:44:57 +05303871 if (voice_is_call_state_active(adev) &&
3872 out == adev->primary_output) {
3873 ALOGD("%s: SSR/PDR occurred, end all calls", __func__);
3874 pthread_mutex_lock(&adev->lock);
3875 voice_stop_call(adev);
3876 adev->mode = AUDIO_MODE_NORMAL;
3877 pthread_mutex_unlock(&adev->lock);
3878 }
3879 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303880 return;
3881}
3882
Kevin Rocardfce19002017-08-07 19:21:36 -07003883static int get_alive_usb_card(struct str_parms* parms) {
3884 int card;
3885 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
3886 !audio_extn_usb_alive(card)) {
3887 return card;
3888 }
3889 return -ENODEV;
3890}
3891
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003892static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3893{
3894 struct stream_out *out = (struct stream_out *)stream;
3895 struct audio_device *adev = out->dev;
3896 struct str_parms *parms;
3897 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003898 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303899 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003900 bool reconfig = false;
3901 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003902
sangwoobc677242013-08-08 16:53:43 +09003903 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003904 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003905 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303906 if (!parms)
3907 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003908 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3909 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003910 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003911 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003912 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003914 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003915 * When HDMI cable is unplugged the music playback is paused and
3916 * the policy manager sends routing=0. But the audioflinger continues
3917 * to write data until standby time (3sec). As the HDMI core is
3918 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003919 * Avoid this by routing audio to speaker until standby.
3920 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003921 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3922 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303923 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003924 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3925 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003926 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303927 /*
3928 * When A2DP is disconnected the
3929 * music playback is paused and the policy manager sends routing=0
3930 * But the audioflingercontinues to write data until standby time
3931 * (3sec). As BT is turned off, the write gets blocked.
3932 * Avoid this by routing audio to speaker until standby.
3933 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003934 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07003935 (val == AUDIO_DEVICE_NONE) &&
3936 !audio_extn_a2dp_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303937 val = AUDIO_DEVICE_OUT_SPEAKER;
3938 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05303939 /*
3940 * When USB headset is disconnected the music platback paused
3941 * and the policy manager send routing=0. But if the USB is connected
3942 * back before the standby time, AFE is not closed and opened
3943 * when USB is connected back. So routing to speker will guarantee
3944 * AFE reconfiguration and AFE will be opend once USB is connected again
3945 */
3946 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
3947 (val == AUDIO_DEVICE_NONE) &&
3948 !audio_extn_usb_connected(parms)) {
3949 val = AUDIO_DEVICE_OUT_SPEAKER;
3950 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303951 /* To avoid a2dp to sco overlapping / BT device improper state
3952 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303953 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303954 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3955 if (!audio_extn_a2dp_is_ready()) {
3956 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3957 //combo usecase just by pass a2dp
3958 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303959 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303960 } else {
3961 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3962 /* update device to a2dp and don't route as BT returned error
3963 * However it is still possible a2dp routing called because
3964 * of current active device disconnection (like wired headset)
3965 */
3966 out->devices = val;
3967 pthread_mutex_unlock(&out->lock);
3968 pthread_mutex_unlock(&adev->lock);
3969 goto error;
3970 }
3971 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303972 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003973
3974 audio_devices_t new_dev = val;
3975
3976 // Workaround: If routing to an non existing usb device, fail gracefully
3977 // The routing request will otherwise block during 10 second
3978 int card;
3979 if (audio_is_usb_out_device(new_dev) &&
3980 (card = get_alive_usb_card(parms)) >= 0) {
3981
3982 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
3983 pthread_mutex_unlock(&adev->lock);
3984 pthread_mutex_unlock(&out->lock);
3985 ret = -ENOSYS;
3986 goto routing_fail;
3987 }
3988
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003989 /*
3990 * select_devices() call below switches all the usecases on the same
3991 * backend to the new device. Refer to check_usecases_codec_backend() in
3992 * the select_devices(). But how do we undo this?
3993 *
3994 * For example, music playback is active on headset (deep-buffer usecase)
3995 * and if we go to ringtones and select a ringtone, low-latency usecase
3996 * will be started on headset+speaker. As we can't enable headset+speaker
3997 * and headset devices at the same time, select_devices() switches the music
3998 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3999 * So when the ringtone playback is completed, how do we undo the same?
4000 *
4001 * We are relying on the out_set_parameters() call on deep-buffer output,
4002 * once the ringtone playback is ended.
4003 * NOTE: We should not check if the current devices are same as new devices.
4004 * Because select_devices() must be called to switch back the music
4005 * playback to headset.
4006 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004007 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004008 audio_devices_t new_dev = val;
4009 bool same_dev = out->devices == new_dev;
4010 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004011
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004012 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004013 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004014 if (adev->mode == AUDIO_MODE_IN_CALL) {
4015 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004016 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4017 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4018 audio_extn_usb_set_service_interval(true /*playback*/,
4019 service_interval,
4020 &reconfig);
4021 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4022 }
4023 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004024 }
4025 } else {
4026 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004027 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004028 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004029 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004030
4031 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004032 if (!same_dev) {
4033 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304034 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4035 adev->perf_lock_opts,
4036 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004037 if (adev->adm_on_routing_change)
4038 adev->adm_on_routing_change(adev->adm_data,
4039 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004040 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304041 if (!bypass_a2dp) {
4042 select_devices(adev, out->usecase);
4043 } else {
4044 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
4045 select_devices(adev, out->usecase);
4046 out->devices = new_dev;
4047 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004048
4049 if (!same_dev) {
4050 // on device switch force swap, lower functions will make sure
4051 // to check if swap is allowed or not.
4052 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304053 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004054 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304055 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4056 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08004057 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304058 pthread_mutex_lock(&out->compr_mute_lock);
4059 out->a2dp_compress_mute = false;
4060 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4061 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004062 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4063 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304064 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004065 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004066 }
4067
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004068 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004069 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004070 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004071 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004072
4073 if (out == adev->primary_output) {
4074 pthread_mutex_lock(&adev->lock);
4075 audio_extn_set_parameters(adev, parms);
4076 pthread_mutex_unlock(&adev->lock);
4077 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004078 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004079 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004080 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004081
4082 audio_extn_dts_create_state_notifier_node(out->usecase);
4083 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4084 popcount(out->channel_mask),
4085 out->playback_started);
4086
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004087 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004088 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004089
Surendar Karka5a18a7a2018-04-26 11:28:38 +05304090 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4091 sizeof(value));
4092 if (err >= 0) {
4093 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4094 audio_extn_send_dual_mono_mixing_coefficients(out);
4095 }
4096
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304097 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4098 if (err >= 0) {
4099 strlcpy(out->profile, value, sizeof(out->profile));
4100 ALOGV("updating stream profile with value '%s'", out->profile);
4101 lock_output_stream(out);
4102 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4103 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004104 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304105 out->sample_rate, out->bit_width,
4106 out->channel_mask, out->profile,
4107 &out->app_type_cfg);
4108 pthread_mutex_unlock(&out->lock);
4109 }
4110
Alexy Joseph98988832017-01-13 14:56:59 -08004111 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004112 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4113 // and vendor.audio.hal.output.suspend.supported is set to true
4114 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004115 //check suspend parameter only for low latency and if the property
4116 //is enabled
4117 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4118 ALOGI("%s: got suspend_playback %s", __func__, value);
4119 lock_output_stream(out);
4120 if (!strncmp(value, "false", 5)) {
4121 //suspend_playback=false is supposed to set QOS value back to 75%
4122 //the mixer control sent with value Enable will achieve that
4123 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4124 } else if (!strncmp (value, "true", 4)) {
4125 //suspend_playback=true is supposed to remove QOS value
4126 //resetting the mixer control will set the default value
4127 //for the mixer control which is Disable and this removes the QOS vote
4128 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4129 } else {
4130 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4131 " got %s", __func__, value);
4132 ret = -1;
4133 }
4134
4135 if (ret != 0) {
4136 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4137 __func__, out->pm_qos_mixer_path, ret);
4138 }
4139
4140 pthread_mutex_unlock(&out->lock);
4141 }
4142 }
4143 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004144 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304145error:
Eric Laurent994a6932013-07-17 11:51:42 -07004146 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147 return ret;
4148}
4149
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004150static bool stream_get_parameter_channels(struct str_parms *query,
4151 struct str_parms *reply,
4152 audio_channel_mask_t *supported_channel_masks) {
4153 int ret = -1;
4154 char value[512];
4155 bool first = true;
4156 size_t i, j;
4157
4158 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4159 ret = 0;
4160 value[0] = '\0';
4161 i = 0;
4162 while (supported_channel_masks[i] != 0) {
4163 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4164 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4165 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304166 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004167
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304168 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004169 first = false;
4170 break;
4171 }
4172 }
4173 i++;
4174 }
4175 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4176 }
4177 return ret == 0;
4178}
4179
4180static bool stream_get_parameter_formats(struct str_parms *query,
4181 struct str_parms *reply,
4182 audio_format_t *supported_formats) {
4183 int ret = -1;
4184 char value[256];
4185 size_t i, j;
4186 bool first = true;
4187
4188 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4189 ret = 0;
4190 value[0] = '\0';
4191 i = 0;
4192 while (supported_formats[i] != 0) {
4193 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4194 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4195 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304196 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004197 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304198 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004199 first = false;
4200 break;
4201 }
4202 }
4203 i++;
4204 }
4205 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4206 }
4207 return ret == 0;
4208}
4209
4210static bool stream_get_parameter_rates(struct str_parms *query,
4211 struct str_parms *reply,
4212 uint32_t *supported_sample_rates) {
4213
4214 int i;
4215 char value[256];
4216 int ret = -1;
4217 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4218 ret = 0;
4219 value[0] = '\0';
4220 i=0;
4221 int cursor = 0;
4222 while (supported_sample_rates[i]) {
4223 int avail = sizeof(value) - cursor;
4224 ret = snprintf(value + cursor, avail, "%s%d",
4225 cursor > 0 ? "|" : "",
4226 supported_sample_rates[i]);
4227 if (ret < 0 || ret >= avail) {
4228 // if cursor is at the last element of the array
4229 // overwrite with \0 is duplicate work as
4230 // snprintf already put a \0 in place.
4231 // else
4232 // we had space to write the '|' at value[cursor]
4233 // (which will be overwritten) or no space to fill
4234 // the first element (=> cursor == 0)
4235 value[cursor] = '\0';
4236 break;
4237 }
4238 cursor += ret;
4239 ++i;
4240 }
4241 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4242 value);
4243 }
4244 return ret >= 0;
4245}
4246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4248{
4249 struct stream_out *out = (struct stream_out *)stream;
4250 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004251 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004252 char value[256];
4253 struct str_parms *reply = str_parms_create();
4254 size_t i, j;
4255 int ret;
4256 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004257
4258 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004259 if (reply) {
4260 str_parms_destroy(reply);
4261 }
4262 if (query) {
4263 str_parms_destroy(query);
4264 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004265 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4266 return NULL;
4267 }
4268
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004269 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004270 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4271 if (ret >= 0) {
4272 value[0] = '\0';
4273 i = 0;
4274 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004275 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4276 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004277 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004278 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004279 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004280 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004281 first = false;
4282 break;
4283 }
4284 }
4285 i++;
4286 }
4287 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4288 str = str_parms_to_str(reply);
4289 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004290 voice_extn_out_get_parameters(out, query, reply);
4291 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004292 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004293
Alexy Joseph62142aa2015-11-16 15:10:34 -08004294
4295 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4296 if (ret >= 0) {
4297 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304298 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4299 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004300 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304301 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004302 } else {
4303 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304304 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004305 }
4306 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004307 if (str)
4308 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004309 str = str_parms_to_str(reply);
4310 }
4311
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004312 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4313 if (ret >= 0) {
4314 value[0] = '\0';
4315 i = 0;
4316 first = true;
4317 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004318 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4319 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004320 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004321 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004322 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004323 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004324 first = false;
4325 break;
4326 }
4327 }
4328 i++;
4329 }
4330 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004331 if (str)
4332 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004333 str = str_parms_to_str(reply);
4334 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004335
4336 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4337 if (ret >= 0) {
4338 value[0] = '\0';
4339 i = 0;
4340 first = true;
4341 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004342 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4343 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004344 if (!first) {
4345 strlcat(value, "|", sizeof(value));
4346 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004347 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004348 first = false;
4349 break;
4350 }
4351 }
4352 i++;
4353 }
4354 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4355 if (str)
4356 free(str);
4357 str = str_parms_to_str(reply);
4358 }
4359
Alexy Joseph98988832017-01-13 14:56:59 -08004360 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4361 //only low latency track supports suspend_resume
4362 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004363 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004364 if (str)
4365 free(str);
4366 str = str_parms_to_str(reply);
4367 }
4368
4369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004370 str_parms_destroy(query);
4371 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004372 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004373 return str;
4374}
4375
4376static uint32_t out_get_latency(const struct audio_stream_out *stream)
4377{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004378 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004379 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004380 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381
Alexy Josephaa54c872014-12-03 02:46:47 -08004382 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304383 lock_output_stream(out);
4384 latency = audio_extn_utils_compress_get_dsp_latency(out);
4385 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004386 } else if ((out->realtime) ||
4387 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004388 // since the buffer won't be filled up faster than realtime,
4389 // return a smaller number
4390 if (out->config.rate)
4391 period_ms = (out->af_period_multiplier * out->config.period_size *
4392 1000) / (out->config.rate);
4393 else
4394 period_ms = 0;
4395 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004396 } else {
4397 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004398 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004399 }
4400
yidongh0515e042017-07-06 15:00:34 +08004401 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004402 latency += audio_extn_a2dp_get_encoder_latency();
4403
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304404 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004405 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004406}
4407
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304408static float AmpToDb(float amplification)
4409{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304410 float db = DSD_VOLUME_MIN_DB;
4411 if (amplification > 0) {
4412 db = 20 * log10(amplification);
4413 if(db < DSD_VOLUME_MIN_DB)
4414 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304415 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304416 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304417}
4418
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004419static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4420 float right)
4421{
4422 struct stream_out *out = (struct stream_out *)stream;
4423 long volume = 0;
4424 char mixer_ctl_name[128] = "";
4425 struct audio_device *adev = out->dev;
4426 struct mixer_ctl *ctl = NULL;
4427 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4428 PCM_PLAYBACK);
4429
4430 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4431 "Playback %d Volume", pcm_device_id);
4432 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4433 if (!ctl) {
4434 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4435 __func__, mixer_ctl_name);
4436 return -EINVAL;
4437 }
4438 if (left != right)
4439 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4440 __func__, left, right);
4441 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4442 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4443 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4444 __func__, mixer_ctl_name, volume);
4445 return -EINVAL;
4446 }
4447 return 0;
4448}
4449
4450
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304451static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4452 float right)
4453{
4454 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304455 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304456 char mixer_ctl_name[128];
4457 struct audio_device *adev = out->dev;
4458 struct mixer_ctl *ctl;
4459 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4460 PCM_PLAYBACK);
4461
4462 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4463 "Compress Playback %d Volume", pcm_device_id);
4464 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4465 if (!ctl) {
4466 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4467 __func__, mixer_ctl_name);
4468 return -EINVAL;
4469 }
4470 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4471 __func__, mixer_ctl_name, left, right);
4472 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4473 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4474 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4475
4476 return 0;
4477}
4478
Zhou Song2b8f28f2017-09-11 10:51:38 +08004479static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4480 float right)
4481{
4482 struct stream_out *out = (struct stream_out *)stream;
4483 char mixer_ctl_name[] = "App Type Gain";
4484 struct audio_device *adev = out->dev;
4485 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304486 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004487
4488 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4489 if (!ctl) {
4490 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4491 __func__, mixer_ctl_name);
4492 return -EINVAL;
4493 }
4494
4495 set_values[0] = 0; //0: Rx Session 1:Tx Session
4496 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304497 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4498 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004499
4500 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4501 return 0;
4502}
4503
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004504static int out_set_volume(struct audio_stream_out *stream, float left,
4505 float right)
4506{
Eric Laurenta9024de2013-04-04 09:19:12 -07004507 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004508 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304509 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004510
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004511 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
4512
Eric Laurenta9024de2013-04-04 09:19:12 -07004513 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4514 /* only take left channel into account: the API is for stereo anyway */
4515 out->muted = (left == 0.0f);
4516 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004517 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304518 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004519 /*
4520 * Set mute or umute on HDMI passthrough stream.
4521 * Only take left channel into account.
4522 * Mute is 0 and unmute 1
4523 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304524 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304525 } else if (out->format == AUDIO_FORMAT_DSD){
4526 char mixer_ctl_name[128] = "DSD Volume";
4527 struct audio_device *adev = out->dev;
4528 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4529
4530 if (!ctl) {
4531 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4532 __func__, mixer_ctl_name);
4533 return -EINVAL;
4534 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304535 volume[0] = (long)(AmpToDb(left));
4536 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304537 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4538 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004539 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304540 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004541 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304542 if (!out->a2dp_compress_mute)
4543 ret = out_set_compr_volume(stream, left, right);
4544 out->volume_l = left;
4545 out->volume_r = right;
4546 pthread_mutex_unlock(&out->compr_mute_lock);
4547 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004548 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004549 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004550 if (!out->standby)
4551 ret = out_set_voip_volume(stream, left, right);
4552 out->volume_l = left;
4553 out->volume_r = right;
4554 return ret;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004555 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4556 ALOGV("%s: MMAP set volume called", __func__);
4557 if (!out->standby)
4558 ret = out_set_mmap_volume(stream, left, right);
4559 out->volume_l = left;
4560 out->volume_r = right;
4561 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004562 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004563
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004564 return -ENOSYS;
4565}
4566
Zhou Songc9672822017-08-16 16:01:39 +08004567static void update_frames_written(struct stream_out *out, size_t bytes)
4568{
4569 size_t bpf = 0;
4570
4571 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4572 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4573 bpf = 1;
4574 else if (!is_offload_usecase(out->usecase))
4575 bpf = audio_bytes_per_sample(out->format) *
4576 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004577
4578 pthread_mutex_lock(&out->position_query_lock);
4579 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004580 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004581 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4582 }
4583 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004584}
4585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004586static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4587 size_t bytes)
4588{
4589 struct stream_out *out = (struct stream_out *)stream;
4590 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004591 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304592 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004593 const size_t frame_size = audio_stream_out_frame_size(stream);
4594 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004595
Haynes Mathew George380745d2017-10-04 15:27:45 -07004596 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004597 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304598
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304599 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004600
Dhananjay Kumarac341582017-02-23 23:42:25 +05304601 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304602 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304603 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4604 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004605 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304606 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304607 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304608 ALOGD(" %s: sound card is not active/SSR state", __func__);
4609 ret= -EIO;
4610 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304611 }
4612 }
4613
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304614 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304615 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304616 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304617 goto exit;
4618 }
4619
Haynes Mathew George16081042017-05-31 17:16:49 -07004620 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4621 ret = -EINVAL;
4622 goto exit;
4623 }
4624
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304625 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4626 !out->is_iec61937_info_available) {
4627
4628 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4629 out->is_iec61937_info_available = true;
4630 } else if (audio_extn_passthru_is_enabled()) {
4631 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304632 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304633
4634 if((out->format == AUDIO_FORMAT_DTS) ||
4635 (out->format == AUDIO_FORMAT_DTS_HD)) {
4636 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4637 buffer, bytes);
4638 if (ret) {
4639 if (ret != -ENOSYS) {
4640 out->is_iec61937_info_available = false;
4641 ALOGD("iec61937 transmission info not yet updated retry");
4642 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304643 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304644 /* if stream has started and after that there is
4645 * stream config change (iec transmission config)
4646 * then trigger select_device to update backend configuration.
4647 */
4648 out->stream_config_changed = true;
4649 pthread_mutex_lock(&adev->lock);
4650 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304651 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4652 ret = -EINVAL;
4653 goto exit;
4654 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304655 pthread_mutex_unlock(&adev->lock);
4656 out->stream_config_changed = false;
4657 out->is_iec61937_info_available = true;
4658 }
4659 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304660
Garmond Leung317cbf12017-09-13 16:20:50 -07004661 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304662 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4663 (out->is_iec61937_info_available == true)) {
4664 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4665 ret = -EINVAL;
4666 goto exit;
4667 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304668 }
4669 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304670
4671 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4672 (audio_extn_a2dp_is_suspended())) {
4673 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4674 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304675 ret = -EIO;
4676 goto exit;
4677 }
4678 }
4679 }
4680
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004681 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004682 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004683 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004684 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4685 ret = voice_extn_compress_voip_start_output_stream(out);
4686 else
4687 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004688 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004689 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004690 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004691 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004692 goto exit;
4693 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304694 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004695 if (last_known_cal_step != -1) {
4696 ALOGD("%s: retry previous failed cal level set", __func__);
4697 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304698 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004699 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304700
4701 if ((out->is_iec61937_info_available == true) &&
4702 (audio_extn_passthru_is_passthrough_stream(out))&&
4703 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4704 ret = -EINVAL;
4705 goto exit;
4706 }
Surendar Karka5a18a7a2018-04-26 11:28:38 +05304707 if (out->set_dual_mono)
4708 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004709 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004710
Ashish Jain81eb2a82015-05-13 10:52:34 +05304711 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004712 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304713 adev->is_channel_status_set = true;
4714 }
4715
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004716 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004717 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004718 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004719 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004720 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4721 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304722 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4723 ALOGD("copl(%p):send next track params in gapless", out);
4724 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4725 out->send_next_track_params = false;
4726 out->is_compr_metadata_avail = false;
4727 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004728 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304729 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304730 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004731
Ashish Jain83a6cc22016-06-28 14:34:17 +05304732 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304733 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304734 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304735 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004736 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304737 return -EINVAL;
4738 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304739 audio_format_t dst_format = out->hal_op_format;
4740 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304741
4742 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4743 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4744
Ashish Jain83a6cc22016-06-28 14:34:17 +05304745 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304746 dst_format,
4747 buffer,
4748 src_format,
4749 frames);
4750
Ashish Jain83a6cc22016-06-28 14:34:17 +05304751 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304752 bytes_to_write);
4753
4754 /*Convert written bytes in audio flinger format*/
4755 if (ret > 0)
4756 ret = ((ret * format_to_bitwidth_table[out->format]) /
4757 format_to_bitwidth_table[dst_format]);
4758 }
4759 } else
4760 ret = compress_write(out->compr, buffer, bytes);
4761
Zhou Songc9672822017-08-16 16:01:39 +08004762 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4763 update_frames_written(out, bytes);
4764
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304765 if (ret < 0)
4766 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08004767 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304768 /*msg to cb thread only if non blocking write is enabled*/
4769 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304770 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004771 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304772 } else if (-ENETRESET == ret) {
4773 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304774 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304775 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304776 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004777 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304778 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004779 }
Ashish Jain5106d362016-05-11 19:23:33 +05304780
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304781 /* Call compr start only when non-zero bytes of data is there to be rendered */
4782 if (!out->playback_started && ret > 0) {
4783 int status = compress_start(out->compr);
4784 if (status < 0) {
4785 ret = status;
4786 ALOGE("%s: compr start failed with err %d", __func__, errno);
4787 goto exit;
4788 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004789 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004790 out->playback_started = 1;
4791 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004792
4793 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4794 popcount(out->channel_mask),
4795 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004796 }
4797 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004798 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004799 return ret;
4800 } else {
4801 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004802 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004803 if (out->muted)
4804 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004805 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
4806 __func__, frames, frame_size, bytes_to_write);
4807
Arun Mirpuridbef0c72018-09-12 18:36:10 -07004808 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4809 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004810 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4811 int16_t *src = (int16_t *)buffer;
4812 int16_t *dst = (int16_t *)buffer;
4813
4814 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
4815 out->format != AUDIO_FORMAT_PCM_16_BIT,
4816 "out_write called for incall music use case with wrong properties");
4817
4818 /*
4819 * FIXME: this can be removed once audio flinger mixer supports
4820 * mono output
4821 */
4822
4823 /*
4824 * Code below goes over each frame in the buffer and adds both
4825 * L and R samples and then divides by 2 to convert to mono
4826 */
4827 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
4828 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
4829 }
4830 bytes_to_write /= 2;
4831 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004832
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304833 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004834
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004835 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004836
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004837 if (out->config.rate)
4838 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4839 out->config.rate;
4840
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004841 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004842 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4843
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004844 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004845 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004846 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304847 out->convert_buffer != NULL) {
4848
4849 memcpy_by_audio_format(out->convert_buffer,
4850 out->hal_op_format,
4851 buffer,
4852 out->hal_ip_format,
4853 out->config.period_size * out->config.channels);
4854
4855 ret = pcm_write(out->pcm, out->convert_buffer,
4856 (out->config.period_size *
4857 out->config.channels *
4858 format_to_bitwidth_table[out->hal_op_format]));
4859 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304860 /*
4861 * To avoid underrun in DSP when the application is not pumping
4862 * data at required rate, check for the no. of bytes and ignore
4863 * pcm_write if it is less than actual buffer size.
4864 * It is a work around to a change in compress VOIP driver.
4865 */
4866 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4867 bytes < (out->config.period_size * out->config.channels *
4868 audio_bytes_per_sample(out->format))) {
4869 size_t voip_buf_size =
4870 out->config.period_size * out->config.channels *
4871 audio_bytes_per_sample(out->format);
4872 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4873 __func__, bytes, voip_buf_size);
4874 usleep(((uint64_t)voip_buf_size - bytes) *
4875 1000000 / audio_stream_out_frame_size(stream) /
4876 out_get_sample_rate(&out->stream.common));
4877 ret = 0;
4878 } else
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004879 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304880 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004881
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004882 release_out_focus(out);
4883
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304884 if (ret < 0)
4885 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004886 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304887 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004888 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004889 }
4890
4891exit:
Zhou Songc9672822017-08-16 16:01:39 +08004892 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304893 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304894 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304895 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004896 pthread_mutex_unlock(&out->lock);
4897
4898 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004899 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004900 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304901 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304902 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304903 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304904 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304905 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304906 out->standby = true;
4907 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304908 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304909 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4910 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4911 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004912
4913 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05304914 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004915 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004916 return ret;
4917 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004918 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004919 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004920 return bytes;
4921}
4922
4923static int out_get_render_position(const struct audio_stream_out *stream,
4924 uint32_t *dsp_frames)
4925{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004926 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004927
4928 if (dsp_frames == NULL)
4929 return -EINVAL;
4930
4931 *dsp_frames = 0;
4932 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004933 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304934
4935 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4936 * this operation and adev_close_output_stream(where out gets reset).
4937 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304938 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004939 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05304940 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004941 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304942 return 0;
4943 }
4944
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004945 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304946 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304947 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004948 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304949 if (ret < 0)
4950 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004951 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304952 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004953 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304954 if (-ENETRESET == ret) {
4955 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304956 out->card_status = CARD_STATUS_OFFLINE;
4957 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304958 } else if(ret < 0) {
4959 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304960 ret = -EINVAL;
4961 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304962 /*
4963 * Handle corner case where compress session is closed during SSR
4964 * and timestamp is queried
4965 */
4966 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304967 ret = -EINVAL;
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05304968 } else if (out->prev_card_status_offline) {
4969 ALOGE("ERROR: previously sound card was offline,return error");
4970 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304971 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304972 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004973 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05304974 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304975 pthread_mutex_unlock(&out->lock);
4976 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004977 } else if (audio_is_linear_pcm(out->format)) {
4978 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004979 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08004980 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004981 } else
4982 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004983}
4984
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004985static int out_add_audio_effect(const struct audio_stream *stream __unused,
4986 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004987{
4988 return 0;
4989}
4990
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004991static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4992 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004993{
4994 return 0;
4995}
4996
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004997static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4998 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004999{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305000 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005001}
5002
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005003static int out_get_presentation_position(const struct audio_stream_out *stream,
5004 uint64_t *frames, struct timespec *timestamp)
5005{
5006 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305007 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005008 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005009
Ashish Jain5106d362016-05-11 19:23:33 +05305010 /* below piece of code is not guarded against any lock because audioFliner serializes
5011 * this operation and adev_close_output_stream( where out gets reset).
5012 */
5013 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305014 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005015 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305016 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5017 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5018 return 0;
5019 }
5020
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005021 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005022
Ashish Jain5106d362016-05-11 19:23:33 +05305023 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5024 ret = compress_get_tstamp(out->compr, &dsp_frames,
5025 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005026 // Adjustment accounts for A2dp encoder latency with offload usecases
5027 // Note: Encoder latency is returned in ms.
5028 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5029 unsigned long offset =
5030 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5031 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5032 }
Ashish Jain5106d362016-05-11 19:23:33 +05305033 ALOGVV("%s rendered frames %ld sample_rate %d",
5034 __func__, dsp_frames, out->sample_rate);
5035 *frames = dsp_frames;
5036 if (ret < 0)
5037 ret = -errno;
5038 if (-ENETRESET == ret) {
5039 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305040 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305041 ret = -EINVAL;
5042 } else
5043 ret = 0;
5044 /* this is the best we can do */
5045 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005046 } else {
5047 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005048 unsigned int avail;
5049 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5050 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5051 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5052 // This adjustment accounts for buffering after app processor.
5053 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005054 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005055 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005056
Weiyin Jiangd4633762018-03-16 12:05:03 +08005057 // Adjustment accounts for A2dp encoder latency with non offload usecases
5058 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5059 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5060 signed_frames -=
5061 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5062 }
5063
5064 // It would be unusual for this value to be negative, but check just in case ...
5065 if (signed_frames >= 0) {
5066 *frames = signed_frames;
5067 ret = 0;
5068 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005069 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305070 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305071 *frames = out->written;
5072 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05305073 if (is_offload_usecase(out->usecase))
5074 ret = -EINVAL;
5075 else
5076 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005077 }
5078 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005079 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005080 return ret;
5081}
5082
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005083static int out_set_callback(struct audio_stream_out *stream,
5084 stream_callback_t callback, void *cookie)
5085{
5086 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005087 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005088
5089 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005090 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005091 out->client_callback = callback;
5092 out->client_cookie = cookie;
5093 if (out->adsp_hdlr_stream_handle) {
5094 ret = audio_extn_adsp_hdlr_stream_set_callback(
5095 out->adsp_hdlr_stream_handle,
5096 callback,
5097 cookie);
5098 if (ret)
5099 ALOGW("%s:adsp hdlr callback registration failed %d",
5100 __func__, ret);
5101 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005102 pthread_mutex_unlock(&out->lock);
5103 return 0;
5104}
5105
5106static int out_pause(struct audio_stream_out* stream)
5107{
5108 struct stream_out *out = (struct stream_out *)stream;
5109 int status = -ENOSYS;
5110 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005111 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005112 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005113 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005114 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305115 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305116 status = compress_pause(out->compr);
5117
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005118 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005119
Mingming Yin21854652016-04-13 11:54:02 -07005120 if (audio_extn_passthru_is_active()) {
5121 ALOGV("offload use case, pause passthru");
5122 audio_extn_passthru_on_pause(out);
5123 }
5124
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305125 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005126 audio_extn_dts_notify_playback_state(out->usecase, 0,
5127 out->sample_rate, popcount(out->channel_mask),
5128 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005129 }
5130 pthread_mutex_unlock(&out->lock);
5131 }
5132 return status;
5133}
5134
5135static int out_resume(struct audio_stream_out* stream)
5136{
5137 struct stream_out *out = (struct stream_out *)stream;
5138 int status = -ENOSYS;
5139 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005140 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005141 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005142 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005143 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005144 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305145 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305146 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005147 }
5148 if (!status) {
5149 out->offload_state = OFFLOAD_STATE_PLAYING;
5150 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305151 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005152 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5153 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005154 }
5155 pthread_mutex_unlock(&out->lock);
5156 }
5157 return status;
5158}
5159
5160static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5161{
5162 struct stream_out *out = (struct stream_out *)stream;
5163 int status = -ENOSYS;
5164 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005165 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005166 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005167 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5168 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5169 else
5170 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5171 pthread_mutex_unlock(&out->lock);
5172 }
5173 return status;
5174}
5175
5176static int out_flush(struct audio_stream_out* stream)
5177{
5178 struct stream_out *out = (struct stream_out *)stream;
5179 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005180 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005181 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005182 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005183 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5184 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005185 } else {
5186 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5187 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005188 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005189 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005190 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005191 return 0;
5192 }
5193 return -ENOSYS;
5194}
5195
Haynes Mathew George16081042017-05-31 17:16:49 -07005196static int out_stop(const struct audio_stream_out* stream)
5197{
5198 struct stream_out *out = (struct stream_out *)stream;
5199 struct audio_device *adev = out->dev;
5200 int ret = -ENOSYS;
5201
5202 ALOGV("%s", __func__);
5203 pthread_mutex_lock(&adev->lock);
5204 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5205 out->playback_started && out->pcm != NULL) {
5206 pcm_stop(out->pcm);
5207 ret = stop_output_stream(out);
5208 out->playback_started = false;
5209 }
5210 pthread_mutex_unlock(&adev->lock);
5211 return ret;
5212}
5213
5214static int out_start(const struct audio_stream_out* stream)
5215{
5216 struct stream_out *out = (struct stream_out *)stream;
5217 struct audio_device *adev = out->dev;
5218 int ret = -ENOSYS;
5219
5220 ALOGV("%s", __func__);
5221 pthread_mutex_lock(&adev->lock);
5222 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5223 !out->playback_started && out->pcm != NULL) {
5224 ret = start_output_stream(out);
5225 if (ret == 0) {
5226 out->playback_started = true;
5227 }
5228 }
5229 pthread_mutex_unlock(&adev->lock);
5230 return ret;
5231}
5232
5233/*
5234 * Modify config->period_count based on min_size_frames
5235 */
5236static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5237{
5238 int periodCountRequested = (min_size_frames + config->period_size - 1)
5239 / config->period_size;
5240 int periodCount = MMAP_PERIOD_COUNT_MIN;
5241
5242 ALOGV("%s original config.period_size = %d config.period_count = %d",
5243 __func__, config->period_size, config->period_count);
5244
5245 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5246 periodCount *= 2;
5247 }
5248 config->period_count = periodCount;
5249
5250 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5251}
5252
5253static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5254 int32_t min_size_frames,
5255 struct audio_mmap_buffer_info *info)
5256{
5257 struct stream_out *out = (struct stream_out *)stream;
5258 struct audio_device *adev = out->dev;
5259 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005260 unsigned int offset1 = 0;
5261 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005262 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005263 uint32_t mmap_size;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005264 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005265
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005266 ALOGD("%s", __func__);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305267 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005268 pthread_mutex_lock(&adev->lock);
5269
Sharad Sangle90e613f2018-05-04 16:15:38 +05305270 if (CARD_STATUS_OFFLINE == out->card_status ||
5271 CARD_STATUS_OFFLINE == adev->card_status) {
5272 ALOGW("out->card_status or adev->card_status offline, try again");
5273 ret = -EIO;
5274 goto exit;
5275 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005276 if (info == NULL || min_size_frames == 0) {
5277 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5278 ret = -EINVAL;
5279 goto exit;
5280 }
5281 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5282 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5283 ret = -ENOSYS;
5284 goto exit;
5285 }
5286 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5287 if (out->pcm_device_id < 0) {
5288 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5289 __func__, out->pcm_device_id, out->usecase);
5290 ret = -EINVAL;
5291 goto exit;
5292 }
5293
5294 adjust_mmap_period_count(&out->config, min_size_frames);
5295
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005296 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005297 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5298 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5299 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305300 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
5301 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5302 out->card_status = CARD_STATUS_OFFLINE;
5303 adev->card_status = CARD_STATUS_OFFLINE;
5304 ret = -EIO;
5305 goto exit;
5306 }
5307
Haynes Mathew George16081042017-05-31 17:16:49 -07005308 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5309 step = "open";
5310 ret = -ENODEV;
5311 goto exit;
5312 }
5313 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5314 if (ret < 0) {
5315 step = "begin";
5316 goto exit;
5317 }
5318 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005319 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005320 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005321 ret = platform_get_mmap_data_fd(adev->platform,
5322 out->pcm_device_id, 0 /*playback*/,
5323 &info->shared_memory_fd,
5324 &mmap_size);
5325 if (ret < 0) {
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005326 // Fall back to non exclusive mode
5327 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5328 } else {
5329 if (mmap_size < buffer_size) {
5330 step = "mmap";
5331 goto exit;
5332 }
5333 // FIXME: indicate exclusive mode support by returning a negative buffer size
5334 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005335 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005336 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07005337
5338 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5339 if (ret < 0) {
5340 step = "commit";
5341 goto exit;
5342 }
5343
5344 out->standby = false;
5345 ret = 0;
5346
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005347 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005348 __func__, info->shared_memory_address, info->buffer_size_frames);
5349
5350exit:
5351 if (ret != 0) {
5352 if (out->pcm == NULL) {
5353 ALOGE("%s: %s - %d", __func__, step, ret);
5354 } else {
5355 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5356 pcm_close(out->pcm);
5357 out->pcm = NULL;
5358 }
5359 }
5360 pthread_mutex_unlock(&adev->lock);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305361 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005362 return ret;
5363}
5364
5365static int out_get_mmap_position(const struct audio_stream_out *stream,
5366 struct audio_mmap_position *position)
5367{
5368 struct stream_out *out = (struct stream_out *)stream;
5369 ALOGVV("%s", __func__);
5370 if (position == NULL) {
5371 return -EINVAL;
5372 }
5373 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005374 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005375 return -ENOSYS;
5376 }
5377 if (out->pcm == NULL) {
5378 return -ENOSYS;
5379 }
5380
5381 struct timespec ts = { 0, 0 };
5382 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5383 if (ret < 0) {
5384 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5385 return ret;
5386 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005387 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005388 return 0;
5389}
5390
5391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005392/** audio_stream_in implementation **/
5393static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5394{
5395 struct stream_in *in = (struct stream_in *)stream;
5396
5397 return in->config.rate;
5398}
5399
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005400static int in_set_sample_rate(struct audio_stream *stream __unused,
5401 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005402{
5403 return -ENOSYS;
5404}
5405
5406static size_t in_get_buffer_size(const struct audio_stream *stream)
5407{
5408 struct stream_in *in = (struct stream_in *)stream;
5409
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005410 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5411 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005412 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5413 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 -07005414 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5415 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305416 else if(audio_extn_cin_attached_usecase(in->usecase))
5417 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005418
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005419 return in->config.period_size * in->af_period_multiplier *
5420 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005421}
5422
5423static uint32_t in_get_channels(const struct audio_stream *stream)
5424{
5425 struct stream_in *in = (struct stream_in *)stream;
5426
5427 return in->channel_mask;
5428}
5429
5430static audio_format_t in_get_format(const struct audio_stream *stream)
5431{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005432 struct stream_in *in = (struct stream_in *)stream;
5433
5434 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005435}
5436
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005437static int in_set_format(struct audio_stream *stream __unused,
5438 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005439{
5440 return -ENOSYS;
5441}
5442
5443static int in_standby(struct audio_stream *stream)
5444{
5445 struct stream_in *in = (struct stream_in *)stream;
5446 struct audio_device *adev = in->dev;
5447 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305448 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5449 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005450 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305451
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005452 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005453 if (!in->standby && in->is_st_session) {
5454 ALOGD("%s: sound trigger pcm stop lab", __func__);
5455 audio_extn_sound_trigger_stop_lab(in);
5456 in->standby = 1;
5457 }
5458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005459 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005460 if (adev->adm_deregister_stream)
5461 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5462
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005463 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005464 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005465 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005466 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005467 voice_extn_compress_voip_close_input_stream(stream);
5468 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005469 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5470 do_stop = in->capture_started;
5471 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005472 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305473 if (audio_extn_cin_attached_usecase(in->usecase))
5474 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005475 }
5476
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005477 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005478 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005479 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005480 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005481 in->pcm = NULL;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005482 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005483
5484 if (do_stop)
5485 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005486 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005487 }
5488 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005489 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005490 return status;
5491}
5492
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005493static int in_dump(const struct audio_stream *stream __unused,
5494 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005495{
5496 return 0;
5497}
5498
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305499static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5500{
5501 if (!stream || !parms)
5502 return;
5503
5504 struct stream_in *in = (struct stream_in *)stream;
5505 struct audio_device *adev = in->dev;
5506
5507 card_status_t status;
5508 int card;
5509 if (parse_snd_card_status(parms, &card, &status) < 0)
5510 return;
5511
5512 pthread_mutex_lock(&adev->lock);
5513 bool valid_cb = (card == adev->snd_card);
5514 pthread_mutex_unlock(&adev->lock);
5515
5516 if (!valid_cb)
5517 return;
5518
5519 lock_input_stream(in);
5520 if (in->card_status != status)
5521 in->card_status = status;
5522 pthread_mutex_unlock(&in->lock);
5523
5524 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5525 use_case_table[in->usecase],
5526 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5527
5528 // a better solution would be to report error back to AF and let
5529 // it put the stream to standby
5530 if (status == CARD_STATUS_OFFLINE)
5531 in_standby(&in->stream.common);
5532
5533 return;
5534}
5535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005536static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5537{
5538 struct stream_in *in = (struct stream_in *)stream;
5539 struct audio_device *adev = in->dev;
5540 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005541 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005542 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005543
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305544 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005545 parms = str_parms_create_str(kvpairs);
5546
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305547 if (!parms)
5548 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005549 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005550 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005551
5552 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5553 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005554 val = atoi(value);
5555 /* no audio source uses val == 0 */
5556 if ((in->source != val) && (val != 0)) {
5557 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005558 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5559 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5560 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005561 (in->config.rate == 8000 || in->config.rate == 16000 ||
5562 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005563 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005564 err = voice_extn_compress_voip_open_input_stream(in);
5565 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005566 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005567 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005568 }
5569 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005570 }
5571 }
5572
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005573 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5574 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005575 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005576 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5577
5578 // Workaround: If routing to an non existing usb device, fail gracefully
5579 // The routing request will otherwise block during 10 second
5580 int card;
5581 if (audio_is_usb_in_device(val) &&
5582 (card = get_alive_usb_card(parms)) >= 0) {
5583
5584 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5585 ret = -ENOSYS;
5586 } else {
5587
5588 in->device = val;
5589 /* If recording is in progress, change the tx device to new device */
5590 if (!in->standby && !in->is_st_session) {
5591 ALOGV("update input routing change");
5592 // inform adm before actual routing to prevent glitches.
5593 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005594 adev->adm_on_routing_change(adev->adm_data,
5595 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005596 ret = select_devices(adev, in->usecase);
5597 }
5598 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005599 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005600 }
5601 }
5602
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305603 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5604 if (err >= 0) {
5605 strlcpy(in->profile, value, sizeof(in->profile));
5606 ALOGV("updating stream profile with value '%s'", in->profile);
5607 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5608 &adev->streams_input_cfg_list,
5609 in->device, in->flags, in->format,
5610 in->sample_rate, in->bit_width,
5611 in->profile, &in->app_type_cfg);
5612 }
5613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005614 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005615 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005616
5617 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305618error:
Eric Laurent994a6932013-07-17 11:51:42 -07005619 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005620 return ret;
5621}
5622
5623static char* in_get_parameters(const struct audio_stream *stream,
5624 const char *keys)
5625{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005626 struct stream_in *in = (struct stream_in *)stream;
5627 struct str_parms *query = str_parms_create_str(keys);
5628 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005629 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005630
5631 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005632 if (reply) {
5633 str_parms_destroy(reply);
5634 }
5635 if (query) {
5636 str_parms_destroy(query);
5637 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005638 ALOGE("in_get_parameters: failed to create query or reply");
5639 return NULL;
5640 }
5641
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005642 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005643
5644 voice_extn_in_get_parameters(in, query, reply);
5645
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005646 stream_get_parameter_channels(query, reply,
5647 &in->supported_channel_masks[0]);
5648 stream_get_parameter_formats(query, reply,
5649 &in->supported_formats[0]);
5650 stream_get_parameter_rates(query, reply,
5651 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005652 str = str_parms_to_str(reply);
5653 str_parms_destroy(query);
5654 str_parms_destroy(reply);
5655
5656 ALOGV("%s: exit: returns - %s", __func__, str);
5657 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005658}
5659
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005660static int in_set_gain(struct audio_stream_in *stream __unused,
5661 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005662{
5663 return 0;
5664}
5665
5666static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5667 size_t bytes)
5668{
5669 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305670
5671 if (in == NULL) {
5672 ALOGE("%s: stream_in ptr is NULL", __func__);
5673 return -EINVAL;
5674 }
5675
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005676 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305677 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305678 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005679
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005680 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305681
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005682 if (in->is_st_session) {
5683 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5684 /* Read from sound trigger HAL */
5685 audio_extn_sound_trigger_read(in, buffer, bytes);
5686 pthread_mutex_unlock(&in->lock);
5687 return bytes;
5688 }
5689
Haynes Mathew George16081042017-05-31 17:16:49 -07005690 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5691 ret = -ENOSYS;
5692 goto exit;
5693 }
5694
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005695 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005696 pthread_mutex_lock(&adev->lock);
5697 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5698 ret = voice_extn_compress_voip_start_input_stream(in);
5699 else
5700 ret = start_input_stream(in);
5701 pthread_mutex_unlock(&adev->lock);
5702 if (ret != 0) {
5703 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005704 }
5705 in->standby = 0;
5706 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005707
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005708 // what's the duration requested by the client?
5709 long ns = 0;
5710
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305711 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005712 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5713 in->config.rate;
5714
5715 request_in_focus(in, ns);
5716 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005717
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305718 if (audio_extn_cin_attached_usecase(in->usecase)) {
5719 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5720 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305721 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005722 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305723 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005724 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005725 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005726 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005727 } else if (audio_extn_ffv_get_stream() == in) {
5728 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305729 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005730 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305731 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5732 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5733 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5734 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305735 ret = -EINVAL;
5736 goto exit;
5737 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305738 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305739 ret = -errno;
5740 }
5741 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305742 /* bytes read is always set to bytes for non compress usecases */
5743 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005744 }
5745
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005746 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005748 /*
5749 * Instead of writing zeroes here, we could trust the hardware
5750 * to always provide zeroes when muted.
5751 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305752 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5753 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005754 memset(buffer, 0, bytes);
5755
5756exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005757 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305758 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005759 pthread_mutex_unlock(&in->lock);
5760
5761 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305762 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305763 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305764 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305765 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305766 in->standby = true;
5767 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305768 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5769 bytes_read = bytes;
5770 memset(buffer, 0, bytes);
5771 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005772 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005773 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305774 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305775 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005776 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305777 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005778}
5779
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005780static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005781{
5782 return 0;
5783}
5784
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005785static int add_remove_audio_effect(const struct audio_stream *stream,
5786 effect_handle_t effect,
5787 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005788{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005789 struct stream_in *in = (struct stream_in *)stream;
5790 int status = 0;
5791 effect_descriptor_t desc;
5792
5793 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005794 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5795
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005796 if (status != 0)
5797 return status;
5798
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005799 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005800 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08005801 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5802 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005803 in->enable_aec != enable &&
5804 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5805 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005806 if (!in->standby) {
5807 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5808 select_devices(in->dev, in->usecase);
5809 }
5810
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005811 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005812 if (in->enable_ns != enable &&
5813 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5814 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005815 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08005816 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5817 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005818 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5819 select_devices(in->dev, in->usecase);
5820 } else
5821 select_devices(in->dev, in->usecase);
5822 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005823 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005824 pthread_mutex_unlock(&in->dev->lock);
5825 pthread_mutex_unlock(&in->lock);
5826
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005827 return 0;
5828}
5829
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005830static int in_add_audio_effect(const struct audio_stream *stream,
5831 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005832{
Eric Laurent994a6932013-07-17 11:51:42 -07005833 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005834 return add_remove_audio_effect(stream, effect, true);
5835}
5836
5837static int in_remove_audio_effect(const struct audio_stream *stream,
5838 effect_handle_t effect)
5839{
Eric Laurent994a6932013-07-17 11:51:42 -07005840 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005841 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005842}
5843
Haynes Mathew George16081042017-05-31 17:16:49 -07005844static int in_stop(const struct audio_stream_in* stream)
5845{
5846 struct stream_in *in = (struct stream_in *)stream;
5847 struct audio_device *adev = in->dev;
5848
5849 int ret = -ENOSYS;
5850 ALOGV("%s", __func__);
5851 pthread_mutex_lock(&adev->lock);
5852 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5853 in->capture_started && in->pcm != NULL) {
5854 pcm_stop(in->pcm);
5855 ret = stop_input_stream(in);
5856 in->capture_started = false;
5857 }
5858 pthread_mutex_unlock(&adev->lock);
5859 return ret;
5860}
5861
5862static int in_start(const struct audio_stream_in* stream)
5863{
5864 struct stream_in *in = (struct stream_in *)stream;
5865 struct audio_device *adev = in->dev;
5866 int ret = -ENOSYS;
5867
5868 ALOGV("%s in %p", __func__, in);
5869 pthread_mutex_lock(&adev->lock);
5870 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5871 !in->capture_started && in->pcm != NULL) {
5872 if (!in->capture_started) {
5873 ret = start_input_stream(in);
5874 if (ret == 0) {
5875 in->capture_started = true;
5876 }
5877 }
5878 }
5879 pthread_mutex_unlock(&adev->lock);
5880 return ret;
5881}
5882
5883static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5884 int32_t min_size_frames,
5885 struct audio_mmap_buffer_info *info)
5886{
5887 struct stream_in *in = (struct stream_in *)stream;
5888 struct audio_device *adev = in->dev;
5889 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005890 unsigned int offset1 = 0;
5891 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005892 const char *step = "";
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005893 uint32_t mmap_size = 0;
5894 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005895
5896 pthread_mutex_lock(&adev->lock);
5897 ALOGV("%s in %p", __func__, in);
5898
Sharad Sangle90e613f2018-05-04 16:15:38 +05305899 if (CARD_STATUS_OFFLINE == in->card_status||
5900 CARD_STATUS_OFFLINE == adev->card_status) {
5901 ALOGW("in->card_status or adev->card_status offline, try again");
5902 ret = -EIO;
5903 goto exit;
5904 }
5905
Haynes Mathew George16081042017-05-31 17:16:49 -07005906 if (info == NULL || min_size_frames == 0) {
5907 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5908 ret = -EINVAL;
5909 goto exit;
5910 }
5911 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5912 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5913 ALOGV("%s in %p", __func__, in);
5914 ret = -ENOSYS;
5915 goto exit;
5916 }
5917 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5918 if (in->pcm_device_id < 0) {
5919 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5920 __func__, in->pcm_device_id, in->usecase);
5921 ret = -EINVAL;
5922 goto exit;
5923 }
5924
5925 adjust_mmap_period_count(&in->config, min_size_frames);
5926
5927 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5928 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5929 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5930 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305931 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
5932 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5933 in->card_status = CARD_STATUS_OFFLINE;
5934 adev->card_status = CARD_STATUS_OFFLINE;
5935 ret = -EIO;
5936 goto exit;
5937 }
5938
Haynes Mathew George16081042017-05-31 17:16:49 -07005939 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5940 step = "open";
5941 ret = -ENODEV;
5942 goto exit;
5943 }
5944
5945 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5946 if (ret < 0) {
5947 step = "begin";
5948 goto exit;
5949 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005950
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005951 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5952 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
5953 info->burst_size_frames = in->config.period_size;
5954 ret = platform_get_mmap_data_fd(adev->platform,
5955 in->pcm_device_id, 1 /*capture*/,
5956 &info->shared_memory_fd,
5957 &mmap_size);
5958 if (ret < 0) {
5959 // Fall back to non exclusive mode
5960 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
5961 } else {
5962 if (mmap_size < buffer_size) {
5963 step = "mmap";
5964 goto exit;
5965 }
5966 // FIXME: indicate exclusive mode support by returning a negative buffer size
5967 info->buffer_size_frames *= -1;
5968 }
5969
5970 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07005971
5972 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
5973 if (ret < 0) {
5974 step = "commit";
5975 goto exit;
5976 }
5977
5978 in->standby = false;
5979 ret = 0;
5980
5981 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5982 __func__, info->shared_memory_address, info->buffer_size_frames);
5983
5984exit:
5985 if (ret != 0) {
5986 if (in->pcm == NULL) {
5987 ALOGE("%s: %s - %d", __func__, step, ret);
5988 } else {
5989 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
5990 pcm_close(in->pcm);
5991 in->pcm = NULL;
5992 }
5993 }
5994 pthread_mutex_unlock(&adev->lock);
5995 return ret;
5996}
5997
5998static int in_get_mmap_position(const struct audio_stream_in *stream,
5999 struct audio_mmap_position *position)
6000{
6001 struct stream_in *in = (struct stream_in *)stream;
6002 ALOGVV("%s", __func__);
6003 if (position == NULL) {
6004 return -EINVAL;
6005 }
6006 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6007 return -ENOSYS;
6008 }
6009 if (in->pcm == NULL) {
6010 return -ENOSYS;
6011 }
6012 struct timespec ts = { 0, 0 };
6013 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6014 if (ret < 0) {
6015 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6016 return ret;
6017 }
Naresh Tannirua15d7e92018-11-02 09:49:44 +05306018 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07006019 return 0;
6020}
6021
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306022static int in_get_active_microphones(const struct audio_stream_in *stream,
6023 struct audio_microphone_characteristic_t *mic_array,
6024 size_t *mic_count) {
6025 struct stream_in *in = (struct stream_in *)stream;
6026 struct audio_device *adev = in->dev;
6027 ALOGVV("%s", __func__);
6028
6029 lock_input_stream(in);
6030 pthread_mutex_lock(&adev->lock);
6031 int ret = platform_get_active_microphones(adev->platform,
6032 audio_channel_count_from_in_mask(in->channel_mask),
6033 in->usecase, mic_array, mic_count);
6034 pthread_mutex_unlock(&adev->lock);
6035 pthread_mutex_unlock(&in->lock);
6036
6037 return ret;
6038}
6039
6040static int adev_get_microphones(const struct audio_hw_device *dev,
6041 struct audio_microphone_characteristic_t *mic_array,
6042 size_t *mic_count) {
6043 struct audio_device *adev = (struct audio_device *)dev;
6044 ALOGVV("%s", __func__);
6045
6046 pthread_mutex_lock(&adev->lock);
6047 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6048 pthread_mutex_unlock(&adev->lock);
6049
6050 return ret;
6051}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306052int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006053 audio_io_handle_t handle,
6054 audio_devices_t devices,
6055 audio_output_flags_t flags,
6056 struct audio_config *config,
6057 struct audio_stream_out **stream_out,
6058 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006059{
6060 struct audio_device *adev = (struct audio_device *)dev;
6061 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306062 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006063 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006064 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306065 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006066 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6067 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6068 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6069 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006070
kunleizdff872d2018-08-20 14:40:33 +08006071 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006072 is_usb_dev = false;
6073 devices = AUDIO_DEVICE_OUT_SPEAKER;
6074 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6075 __func__, devices);
6076 }
6077
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006078 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306079
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006080 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6081
Mingming Yin3a941d42016-02-17 18:08:05 -08006082 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6083 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306084 devices, flags, &out->stream);
6085
6086
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006087 if (!out) {
6088 return -ENOMEM;
6089 }
6090
Haynes Mathew George204045b2015-02-25 20:32:03 -08006091 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006092 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306093 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006094 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006095 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006097 if (devices == AUDIO_DEVICE_NONE)
6098 devices = AUDIO_DEVICE_OUT_SPEAKER;
6099
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006100 out->flags = flags;
6101 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006102 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006103 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006104 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306105 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306106 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6107 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6108 else
6109 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006110 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006111 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006112 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306113 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306114 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306115 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006116 out->hal_output_suspend_supported = 0;
6117 out->dynamic_pm_qos_config_supported = 0;
Surendar Karka5a18a7a2018-04-26 11:28:38 +05306118 out->set_dual_mono = false;
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05306119 out->prev_card_status_offline = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006120
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306121 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306122 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006123 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6124
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006125 if (audio_is_linear_pcm(out->format) &&
6126 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
6127 pthread_mutex_lock(&adev->lock);
6128 if (is_hdmi) {
6129 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6130 ret = read_hdmi_sink_caps(out);
6131 } else if (is_usb_dev) {
6132 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6133 &config->format,
6134 &out->supported_formats[0],
6135 MAX_SUPPORTED_FORMATS,
6136 &config->channel_mask,
6137 &out->supported_channel_masks[0],
6138 MAX_SUPPORTED_CHANNEL_MASKS,
6139 &config->sample_rate,
6140 &out->supported_sample_rates[0],
6141 MAX_SUPPORTED_SAMPLE_RATES);
6142 ALOGV("plugged dev USB ret %d", ret);
6143 } else {
6144 ret = -1;
6145 }
6146 pthread_mutex_unlock(&adev->lock);
6147 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006148 if (ret == -ENOSYS) {
6149 /* ignore and go with default */
6150 ret = 0;
6151 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006152 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006153 goto error_open;
6154 }
6155 }
6156 }
6157
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006158 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07006159#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006160 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6161 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6162 out->sample_rate == 32000 || out->sample_rate == 48000)) {
6163 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
6164 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
6165 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
6166
6167 out->config = default_pcm_config_voip_copp;
6168 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6169 out->config.rate = out->sample_rate;
6170
6171#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05306172 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006173 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08006174 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006175 ret = voice_extn_compress_voip_open_output_stream(out);
6176 if (ret != 0) {
6177 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6178 __func__, ret);
6179 goto error_open;
6180 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006181#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006182 } else if (audio_is_linear_pcm(out->format) &&
6183 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6184 out->channel_mask = config->channel_mask;
6185 out->sample_rate = config->sample_rate;
6186 out->format = config->format;
6187 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6188 // does this change?
6189 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6190 out->config.rate = config->sample_rate;
6191 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6192 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6193 audio_bytes_per_sample(config->format));
6194 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006195 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306196 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306197 pthread_mutex_lock(&adev->lock);
6198 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6199 pthread_mutex_unlock(&adev->lock);
6200
6201 // reject offload during card offline to allow
6202 // fallback to s/w paths
6203 if (offline) {
6204 ret = -ENODEV;
6205 goto error_open;
6206 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006207
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006208 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6209 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6210 ALOGE("%s: Unsupported Offload information", __func__);
6211 ret = -EINVAL;
6212 goto error_open;
6213 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006214
Atul Khare3fa6e542017-08-09 00:56:17 +05306215 if (config->offload_info.format == 0)
6216 config->offload_info.format = config->format;
6217 if (config->offload_info.sample_rate == 0)
6218 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006219
Mingming Yin90310102013-11-13 16:57:00 -08006220 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306221 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006222 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006223 ret = -EINVAL;
6224 goto error_open;
6225 }
6226
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006227 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6228 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6229 (audio_extn_passthru_is_passthrough_stream(out)) &&
6230 !((config->sample_rate == 48000) ||
6231 (config->sample_rate == 96000) ||
6232 (config->sample_rate == 192000))) {
6233 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6234 __func__, config->sample_rate, config->offload_info.format);
6235 ret = -EINVAL;
6236 goto error_open;
6237 }
6238
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006239 out->compr_config.codec = (struct snd_codec *)
6240 calloc(1, sizeof(struct snd_codec));
6241
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006242 if (!out->compr_config.codec) {
6243 ret = -ENOMEM;
6244 goto error_open;
6245 }
6246
Dhananjay Kumarac341582017-02-23 23:42:25 +05306247 out->stream.pause = out_pause;
6248 out->stream.resume = out_resume;
6249 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306250 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306251 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006252 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306253 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006254 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306255 } else {
6256 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6257 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006258 }
vivek mehta446c3962015-09-14 10:57:35 -07006259
6260 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006261 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6262 config->format == 0 && config->sample_rate == 0 &&
6263 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006264 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006265 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6266 } else {
6267 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6268 ret = -EEXIST;
6269 goto error_open;
6270 }
vivek mehta446c3962015-09-14 10:57:35 -07006271 }
6272
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006273 if (config->offload_info.channel_mask)
6274 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006275 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006276 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006277 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006278 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306279 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006280 ret = -EINVAL;
6281 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006282 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006283
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006284 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006285 out->sample_rate = config->offload_info.sample_rate;
6286
Mingming Yin3ee55c62014-08-04 14:23:35 -07006287 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006288
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306289 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306290 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306291 audio_extn_dolby_send_ddp_endp_params(adev);
6292 audio_extn_dolby_set_dmid(adev);
6293 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006294
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006295 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006296 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006297 out->compr_config.codec->bit_rate =
6298 config->offload_info.bit_rate;
6299 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306300 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006301 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306302 /* Update bit width only for non passthrough usecases.
6303 * For passthrough usecases, the output will always be opened @16 bit
6304 */
6305 if (!audio_extn_passthru_is_passthrough_stream(out))
6306 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306307
6308 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6309 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6310 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6311
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006312 /*TODO: Do we need to change it for passthrough */
6313 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006314
Manish Dewangana6fc5442015-08-24 20:30:31 +05306315 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6316 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306317 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306318 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306319 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6320 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306321
6322 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6323 AUDIO_FORMAT_PCM) {
6324
6325 /*Based on platform support, configure appropriate alsa format for corresponding
6326 *hal input format.
6327 */
6328 out->compr_config.codec->format = hal_format_to_alsa(
6329 config->offload_info.format);
6330
Ashish Jain83a6cc22016-06-28 14:34:17 +05306331 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306332 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306333 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306334
Dhananjay Kumarac341582017-02-23 23:42:25 +05306335 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306336 *hal input format and alsa format might differ based on platform support.
6337 */
6338 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306339 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306340
6341 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6342
6343 /* Check if alsa session is configured with the same format as HAL input format,
6344 * if not then derive correct fragment size needed to accomodate the
6345 * conversion of HAL input format to alsa format.
6346 */
6347 audio_extn_utils_update_direct_pcm_fragment_size(out);
6348
6349 /*if hal input and output fragment size is different this indicates HAL input format is
6350 *not same as the alsa format
6351 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306352 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306353 /*Allocate a buffer to convert input data to the alsa configured format.
6354 *size of convert buffer is equal to the size required to hold one fragment size
6355 *worth of pcm data, this is because flinger does not write more than fragment_size
6356 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306357 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6358 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306359 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6360 ret = -ENOMEM;
6361 goto error_open;
6362 }
6363 }
6364 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6365 out->compr_config.fragment_size =
6366 audio_extn_passthru_get_buffer_size(&config->offload_info);
6367 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6368 } else {
6369 out->compr_config.fragment_size =
6370 platform_get_compress_offload_buffer_size(&config->offload_info);
6371 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6372 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006373
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306374 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6375 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6376 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006377 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306378 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006379
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306380 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6381 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6382 }
6383
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006384 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6385 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006386
Manish Dewangan69426c82017-01-30 17:35:36 +05306387 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6388 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6389 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6390 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6391 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6392 } else {
6393 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6394 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006395
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306396 memset(&out->channel_map_param, 0,
6397 sizeof(struct audio_out_channel_map_param));
6398
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006399 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306400 out->send_next_track_params = false;
6401 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006402 out->offload_state = OFFLOAD_STATE_IDLE;
6403 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006404 out->writeAt.tv_sec = 0;
6405 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006406
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006407 audio_extn_dts_create_state_notifier_node(out->usecase);
6408
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006409 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6410 __func__, config->offload_info.version,
6411 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306412
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306413 /* Check if DSD audio format is supported in codec
6414 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306415 */
6416
6417 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306418 (!platform_check_codec_dsd_support(adev->platform) ||
6419 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306420 ret = -EINVAL;
6421 goto error_open;
6422 }
6423
Ashish Jain5106d362016-05-11 19:23:33 +05306424 /* Disable gapless if any of the following is true
6425 * passthrough playback
6426 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306427 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306428 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306429 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306430 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006431 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306432 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306433 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306434 check_and_set_gapless_mode(adev, false);
6435 } else
6436 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006437
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306438 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006439 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6440 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306441 if (config->format == AUDIO_FORMAT_DSD) {
6442 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6443 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6444 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006445
6446 create_offload_callback_thread(out);
6447
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006448 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006449 switch (config->sample_rate) {
6450 case 0:
6451 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6452 break;
6453 case 8000:
6454 case 16000:
6455 case 48000:
6456 out->sample_rate = config->sample_rate;
6457 break;
6458 default:
6459 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
6460 config->sample_rate);
6461 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6462 ret = -EINVAL;
6463 goto error_open;
6464 }
6465 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6466 switch (config->channel_mask) {
6467 case AUDIO_CHANNEL_NONE:
6468 case AUDIO_CHANNEL_OUT_STEREO:
6469 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6470 break;
6471 default:
6472 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
6473 config->channel_mask);
6474 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6475 ret = -EINVAL;
6476 goto error_open;
6477 }
6478 switch (config->format) {
6479 case AUDIO_FORMAT_DEFAULT:
6480 case AUDIO_FORMAT_PCM_16_BIT:
6481 out->format = AUDIO_FORMAT_PCM_16_BIT;
6482 break;
6483 default:
6484 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
6485 config->format);
6486 config->format = AUDIO_FORMAT_PCM_16_BIT;
6487 ret = -EINVAL;
6488 goto error_open;
6489 }
6490
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306491 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006492 if (ret != 0) {
6493 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006494 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006495 goto error_open;
6496 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006497 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006498 if (config->sample_rate == 0)
6499 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6500 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6501 config->sample_rate != 8000) {
6502 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6503 ret = -EINVAL;
6504 goto error_open;
6505 }
6506 out->sample_rate = config->sample_rate;
6507 out->config.rate = config->sample_rate;
6508 if (config->format == AUDIO_FORMAT_DEFAULT)
6509 config->format = AUDIO_FORMAT_PCM_16_BIT;
6510 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6511 config->format = AUDIO_FORMAT_PCM_16_BIT;
6512 ret = -EINVAL;
6513 goto error_open;
6514 }
6515 out->format = config->format;
6516 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
6517 out->config = pcm_config_afe_proxy_playback;
6518 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006519 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05306520 unsigned int channels = 0;
6521 /*Update config params to default if not set by the caller*/
6522 if (config->sample_rate == 0)
6523 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6524 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6525 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6526 if (config->format == AUDIO_FORMAT_DEFAULT)
6527 config->format = AUDIO_FORMAT_PCM_16_BIT;
6528
6529 channels = audio_channel_count_from_out_mask(out->channel_mask);
6530
Varun Balaraje49253e2017-07-06 19:48:56 +05306531 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6532 out->usecase = get_interactive_usecase(adev);
6533 out->config = pcm_config_low_latency;
6534 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306535 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006536 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6537 out->flags);
6538 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006539 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6540 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6541 out->config = pcm_config_mmap_playback;
6542 out->stream.start = out_start;
6543 out->stream.stop = out_stop;
6544 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6545 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306546 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6547 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006548 out->hal_output_suspend_supported =
6549 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6550 out->dynamic_pm_qos_config_supported =
6551 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6552 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006553 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6554 } else {
6555 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6556 //the mixer path will be a string similar to "low-latency-playback resume"
6557 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6558 strlcat(out->pm_qos_mixer_path,
6559 " resume", MAX_MIXER_PATH_LEN);
6560 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6561 out->pm_qos_mixer_path);
6562 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306563 out->config = pcm_config_low_latency;
6564 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6565 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6566 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306567 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6568 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6569 if (out->config.period_size <= 0) {
6570 ALOGE("Invalid configuration period size is not valid");
6571 ret = -EINVAL;
6572 goto error_open;
6573 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306574 } else {
6575 /* primary path is the default path selected if no other outputs are available/suitable */
6576 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6577 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6578 }
6579 out->hal_ip_format = format = out->format;
6580 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6581 out->hal_op_format = pcm_format_to_hal(out->config.format);
6582 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6583 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006584 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306585 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306586 if (out->hal_ip_format != out->hal_op_format) {
6587 uint32_t buffer_size = out->config.period_size *
6588 format_to_bitwidth_table[out->hal_op_format] *
6589 out->config.channels;
6590 out->convert_buffer = calloc(1, buffer_size);
6591 if (out->convert_buffer == NULL){
6592 ALOGE("Allocation failed for convert buffer for size %d",
6593 out->compr_config.fragment_size);
6594 ret = -ENOMEM;
6595 goto error_open;
6596 }
6597 ALOGD("Convert buffer allocated of size %d", buffer_size);
6598 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006599 }
6600
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006601 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6602 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306603
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006604 /* TODO remove this hardcoding and check why width is zero*/
6605 if (out->bit_width == 0)
6606 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306607 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006608 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006609 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306610 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306611 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006612 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6613 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6614 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006615 if(adev->primary_output == NULL)
6616 adev->primary_output = out;
6617 else {
6618 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006619 ret = -EEXIST;
6620 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006621 }
6622 }
6623
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006624 /* Check if this usecase is already existing */
6625 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006626 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6627 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006628 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006629 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006630 ret = -EEXIST;
6631 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006632 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006633
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006634 pthread_mutex_unlock(&adev->lock);
6635
6636 out->stream.common.get_sample_rate = out_get_sample_rate;
6637 out->stream.common.set_sample_rate = out_set_sample_rate;
6638 out->stream.common.get_buffer_size = out_get_buffer_size;
6639 out->stream.common.get_channels = out_get_channels;
6640 out->stream.common.get_format = out_get_format;
6641 out->stream.common.set_format = out_set_format;
6642 out->stream.common.standby = out_standby;
6643 out->stream.common.dump = out_dump;
6644 out->stream.common.set_parameters = out_set_parameters;
6645 out->stream.common.get_parameters = out_get_parameters;
6646 out->stream.common.add_audio_effect = out_add_audio_effect;
6647 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6648 out->stream.get_latency = out_get_latency;
6649 out->stream.set_volume = out_set_volume;
6650 out->stream.write = out_write;
6651 out->stream.get_render_position = out_get_render_position;
6652 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006653 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006654
Haynes Mathew George16081042017-05-31 17:16:49 -07006655 if (out->realtime)
6656 out->af_period_multiplier = af_period_multiplier;
6657 else
6658 out->af_period_multiplier = 1;
6659
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006660 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006661 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006662 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006663
6664 config->format = out->stream.common.get_format(&out->stream.common);
6665 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6666 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05306667 register_format(out->format, out->supported_formats);
6668 register_channel_mask(out->channel_mask, out->supported_channel_masks);
6669 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006670
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306671 /*
6672 By locking output stream before registering, we allow the callback
6673 to update stream's state only after stream's initial state is set to
6674 adev state.
6675 */
6676 lock_output_stream(out);
6677 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6678 pthread_mutex_lock(&adev->lock);
6679 out->card_status = adev->card_status;
6680 pthread_mutex_unlock(&adev->lock);
6681 pthread_mutex_unlock(&out->lock);
6682
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006683 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306684 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006685 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006686
6687 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6688 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6689 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006690 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306691 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006692 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006693 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306694 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006695 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6696 out->usecase, PCM_PLAYBACK);
6697 hdlr_stream_cfg.flags = out->flags;
6698 hdlr_stream_cfg.type = PCM_PLAYBACK;
6699 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6700 &hdlr_stream_cfg);
6701 if (ret) {
6702 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6703 out->adsp_hdlr_stream_handle = NULL;
6704 }
6705 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306706 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006707 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006708 if (ret < 0) {
6709 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6710 out->ip_hdlr_handle = NULL;
6711 }
6712 }
Eric Laurent994a6932013-07-17 11:51:42 -07006713 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006714 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006715
6716error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306717 if (out->convert_buffer)
6718 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006719 free(out);
6720 *stream_out = NULL;
6721 ALOGD("%s: exit: ret %d", __func__, ret);
6722 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006723}
6724
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306725void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006726 struct audio_stream_out *stream)
6727{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006728 struct stream_out *out = (struct stream_out *)stream;
6729 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006730 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006731
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006732 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306733
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306734 // must deregister from sndmonitor first to prevent races
6735 // between the callback and close_stream
6736 audio_extn_snd_mon_unregister_listener(out);
6737
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006738 /* close adsp hdrl session before standby */
6739 if (out->adsp_hdlr_stream_handle) {
6740 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6741 if (ret)
6742 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6743 out->adsp_hdlr_stream_handle = NULL;
6744 }
6745
Manish Dewangan21a850a2017-08-14 12:03:55 +05306746 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006747 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6748 out->ip_hdlr_handle = NULL;
6749 }
6750
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006751 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306752 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006753 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306754 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306755 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006756 if(ret != 0)
6757 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6758 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006759 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006760 out_standby(&stream->common);
6761
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006762 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006763 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006764 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006765 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006766 if (out->compr_config.codec != NULL)
6767 free(out->compr_config.codec);
6768 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006769
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306770 out->a2dp_compress_mute = false;
6771
Varun Balaraje49253e2017-07-06 19:48:56 +05306772 if (is_interactive_usecase(out->usecase))
6773 free_interactive_usecase(adev, out->usecase);
6774
Ashish Jain83a6cc22016-06-28 14:34:17 +05306775 if (out->convert_buffer != NULL) {
6776 free(out->convert_buffer);
6777 out->convert_buffer = NULL;
6778 }
6779
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006780 if (adev->voice_tx_output == out)
6781 adev->voice_tx_output = NULL;
6782
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306783 if (adev->primary_output == out)
6784 adev->primary_output = NULL;
6785
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006786 pthread_cond_destroy(&out->cond);
6787 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006788 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006789 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006790}
6791
6792static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6793{
6794 struct audio_device *adev = (struct audio_device *)dev;
6795 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006796 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006797 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006798 int ret;
6799 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006800
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006801 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006802 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006803
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306804 if (!parms)
6805 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306806
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306807 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6808 if (ret >= 0) {
6809 /* When set to false, HAL should disable EC and NS */
6810 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6811 adev->bt_sco_on = true;
6812 else
6813 adev->bt_sco_on = false;
6814 }
6815
Naresh Tanniru4c630392014-05-12 01:05:52 +05306816 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006817 status = voice_set_parameters(adev, parms);
6818 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006819 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006820
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006821 status = platform_set_parameters(adev->platform, parms);
6822 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006823 goto done;
6824
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006825 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6826 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006827 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006828 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6829 adev->bluetooth_nrec = true;
6830 else
6831 adev->bluetooth_nrec = false;
6832 }
6833
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006834 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6835 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006836 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6837 adev->screen_off = false;
6838 else
6839 adev->screen_off = true;
6840 }
6841
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006842 ret = str_parms_get_int(parms, "rotation", &val);
6843 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006844 bool reverse_speakers = false;
6845 switch(val) {
6846 // FIXME: note that the code below assumes that the speakers are in the correct placement
6847 // relative to the user when the device is rotated 90deg from its default rotation. This
6848 // assumption is device-specific, not platform-specific like this code.
6849 case 270:
6850 reverse_speakers = true;
6851 break;
6852 case 0:
6853 case 90:
6854 case 180:
6855 break;
6856 default:
6857 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006858 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006859 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006860 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006861 // check and set swap
6862 // - check if orientation changed and speaker active
6863 // - set rotation and cache the rotation value
6864 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006865 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006866 }
6867
Mingming Yin514a8bc2014-07-29 15:22:21 -07006868 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6869 if (ret >= 0) {
6870 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6871 adev->bt_wb_speech_enabled = true;
6872 else
6873 adev->bt_wb_speech_enabled = false;
6874 }
6875
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006876 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6877 if (ret >= 0) {
6878 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306879 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08006880 if (audio_is_output_device(val) &&
6881 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006882 ALOGV("cache new ext disp type and edid");
6883 ret = platform_get_ext_disp_type(adev->platform);
6884 if (ret < 0) {
6885 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05306886 } else {
6887 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006888 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306889 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07006890 /*
6891 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6892 * Per AudioPolicyManager, USB device is higher priority than WFD.
6893 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6894 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6895 * starting voice call on USB
6896 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006897 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306898 if (ret >= 0)
6899 audio_extn_usb_add_device(device, atoi(value));
6900
Zhou Song6f862822017-11-06 17:27:57 +08006901 if (!audio_extn_usb_is_tunnel_supported()) {
6902 ALOGV("detected USB connect .. disable proxy");
6903 adev->allow_afe_proxy_usage = false;
6904 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006905 }
6906 }
6907
6908 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6909 if (ret >= 0) {
6910 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306911 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07006912 /*
6913 * The HDMI / Displayport disconnect handling has been moved to
6914 * audio extension to ensure that its parameters are not
6915 * invalidated prior to updating sysfs of the disconnect event
6916 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6917 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306918 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006919 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306920 if (ret >= 0)
6921 audio_extn_usb_remove_device(device, atoi(value));
6922
Zhou Song6f862822017-11-06 17:27:57 +08006923 if (!audio_extn_usb_is_tunnel_supported()) {
6924 ALOGV("detected USB disconnect .. enable proxy");
6925 adev->allow_afe_proxy_usage = true;
6926 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006927 }
6928 }
6929
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306930 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6931 if (ret >= 0) {
6932 struct audio_usecase *usecase;
6933 struct listnode *node;
6934 list_for_each(node, &adev->usecase_list) {
6935 usecase = node_to_item(node, struct audio_usecase, list);
6936 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07006937 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306938 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08006939
6940 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306941 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08006942 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306943 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306944 //force device switch to re configure encoder
6945 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306946 audio_extn_a2dp_set_handoff_mode(false);
6947 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306948 break;
6949 }
6950 }
6951 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006952
6953 //handle vr audio setparam
6954 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6955 value, sizeof(value));
6956 if (ret >= 0) {
6957 ALOGI("Setting vr mode to be %s", value);
6958 if (!strncmp(value, "true", 4)) {
6959 adev->vr_audio_mode_enabled = true;
6960 ALOGI("Setting vr mode to true");
6961 } else if (!strncmp(value, "false", 5)) {
6962 adev->vr_audio_mode_enabled = false;
6963 ALOGI("Setting vr mode to false");
6964 } else {
6965 ALOGI("wrong vr mode set");
6966 }
6967 }
6968
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306969 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006970done:
6971 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006972 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306973error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006974 ALOGV("%s: exit with code(%d)", __func__, status);
6975 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006976}
6977
6978static char* adev_get_parameters(const struct audio_hw_device *dev,
6979 const char *keys)
6980{
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05306981 ALOGD("%s:%s", __func__, keys);
6982
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006983 struct audio_device *adev = (struct audio_device *)dev;
6984 struct str_parms *reply = str_parms_create();
6985 struct str_parms *query = str_parms_create_str(keys);
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05306986
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006987 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05306988 char value[256] = {0};
6989 int ret = 0;
6990
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006991 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006992 if (reply) {
6993 str_parms_destroy(reply);
6994 }
6995 if (query) {
6996 str_parms_destroy(query);
6997 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006998 ALOGE("adev_get_parameters: failed to create query or reply");
6999 return NULL;
7000 }
7001
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007002 //handle vr audio getparam
7003
7004 ret = str_parms_get_str(query,
7005 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7006 value, sizeof(value));
7007
7008 if (ret >= 0) {
7009 bool vr_audio_enabled = false;
7010 pthread_mutex_lock(&adev->lock);
7011 vr_audio_enabled = adev->vr_audio_mode_enabled;
7012 pthread_mutex_unlock(&adev->lock);
7013
7014 ALOGI("getting vr mode to %d", vr_audio_enabled);
7015
7016 if (vr_audio_enabled) {
7017 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7018 "true");
7019 goto exit;
7020 } else {
7021 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7022 "false");
7023 goto exit;
7024 }
7025 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007026
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007027 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007028 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08007029 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007030 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05307031 pthread_mutex_unlock(&adev->lock);
7032
Naresh Tannirud7205b62014-06-20 02:54:48 +05307033exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007034 str = str_parms_to_str(reply);
7035 str_parms_destroy(query);
7036 str_parms_destroy(reply);
7037
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05307038 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007039 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007040}
7041
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007042static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007043{
7044 return 0;
7045}
7046
7047static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
7048{
Haynes Mathew George5191a852013-09-11 14:19:36 -07007049 int ret;
7050 struct audio_device *adev = (struct audio_device *)dev;
7051 pthread_mutex_lock(&adev->lock);
7052 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07007053 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07007054 pthread_mutex_unlock(&adev->lock);
7055 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007056}
7057
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007058static int adev_set_master_volume(struct audio_hw_device *dev __unused,
7059 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007060{
7061 return -ENOSYS;
7062}
7063
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007064static int adev_get_master_volume(struct audio_hw_device *dev __unused,
7065 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007066{
7067 return -ENOSYS;
7068}
7069
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007070static int adev_set_master_mute(struct audio_hw_device *dev __unused,
7071 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007072{
7073 return -ENOSYS;
7074}
7075
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007076static int adev_get_master_mute(struct audio_hw_device *dev __unused,
7077 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007078{
7079 return -ENOSYS;
7080}
7081
7082static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
7083{
7084 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07007085 struct listnode *node;
7086 struct audio_usecase *usecase = NULL;
7087 int ret = 0;
kunleiz60c17e72017-05-04 12:15:35 +08007088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007089 pthread_mutex_lock(&adev->lock);
7090 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007091 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007092 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08007093 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07007094 list_for_each(node, &adev->usecase_list) {
7095 usecase = node_to_item(node, struct audio_usecase, list);
7096 if (usecase->type == VOICE_CALL)
7097 break;
7098 }
7099 if (usecase &&
7100 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
7101 ret = audio_extn_usb_check_and_set_svc_int(usecase,
7102 true);
7103 if (ret != 0) {
7104 /* default service interval was successfully updated,
7105 reopen USB backend with new service interval */
7106 check_usecases_codec_backend(adev,
7107 usecase,
7108 usecase->out_snd_device);
7109 }
7110 }
7111
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007112 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07007113 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007114 adev->current_call_output = NULL;
kunleiz60c17e72017-05-04 12:15:35 +08007115 // restore device for other active usecases after stop call
7116 list_for_each(node, &adev->usecase_list) {
7117 usecase = node_to_item(node, struct audio_usecase, list);
7118 select_devices(adev, usecase->id);
7119 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007120 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007121 }
7122 pthread_mutex_unlock(&adev->lock);
7123 return 0;
7124}
7125
7126static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
7127{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007128 int ret;
7129
7130 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08007131 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007132 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Derek Chencdd17c72014-11-24 12:39:14 -08007133 if (adev->ext_hw_plugin)
7134 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007135 pthread_mutex_unlock(&adev->lock);
7136
7137 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007138}
7139
7140static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
7141{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007142 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007143 return 0;
7144}
7145
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007146static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007147 const struct audio_config *config)
7148{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007149 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007150
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007151 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
7152 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007153}
7154
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007155static bool adev_input_allow_hifi_record(struct audio_device *adev,
7156 audio_devices_t devices,
7157 audio_input_flags_t flags,
7158 audio_source_t source) {
7159 const bool allowed = true;
7160
7161 if (!audio_is_usb_in_device(devices))
7162 return !allowed;
7163
7164 switch (flags) {
7165 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007166 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07007167 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7168 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007169 default:
7170 return !allowed;
7171 }
7172
7173 switch (source) {
7174 case AUDIO_SOURCE_DEFAULT:
7175 case AUDIO_SOURCE_MIC:
7176 case AUDIO_SOURCE_UNPROCESSED:
7177 break;
7178 default:
7179 return !allowed;
7180 }
7181
7182 switch (adev->mode) {
7183 case 0:
7184 break;
7185 default:
7186 return !allowed;
7187 }
7188
7189 return allowed;
7190}
7191
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007192static int adev_update_voice_comm_input_stream(struct stream_in *in,
7193 struct audio_config *config)
7194{
7195 bool valid_rate = (config->sample_rate == 8000 ||
7196 config->sample_rate == 16000 ||
7197 config->sample_rate == 32000 ||
7198 config->sample_rate == 48000);
7199 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
7200
7201#ifndef COMPRESS_VOIP_ENABLED
kunleizd96526c2018-04-09 11:12:32 +08007202 if (valid_rate && valid_ch &&
7203 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007204 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7205 in->config = default_pcm_config_voip_copp;
7206 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
7207 DEFAULT_VOIP_BUF_DURATION_MS,
7208 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
7209 } else {
kunleizbdd9ad02018-04-24 10:53:17 +08007210 ALOGW("%s No valid input in voip, use defaults"
7211 "sample rate %u, channel mask 0x%X",
7212 __func__, config->sample_rate, in->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007213 }
7214 in->config.rate = config->sample_rate;
7215 in->sample_rate = config->sample_rate;
7216#else
7217 //XXX needed for voice_extn_compress_voip_open_input_stream
7218 in->config.rate = config->sample_rate;
7219 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7220 voice_extn_compress_voip_is_active(in->dev)) &&
7221 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7222 valid_rate && valid_ch) {
7223 voice_extn_compress_voip_open_input_stream(in);
7224 // update rate entries to match config from AF
7225 in->config.rate = config->sample_rate;
7226 in->sample_rate = config->sample_rate;
7227 } else {
7228 ALOGW("%s compress voip not active, use defaults", __func__);
7229 }
7230#endif
7231 return 0;
7232}
7233
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007234static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007235 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007236 audio_devices_t devices,
7237 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007238 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307239 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007240 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007241 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007242{
7243 struct audio_device *adev = (struct audio_device *)dev;
7244 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007245 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007246 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007247 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05307248 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007249 bool is_usb_dev = audio_is_usb_in_device(devices);
7250 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
7251 devices,
7252 flags,
7253 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307254
kunleizdff872d2018-08-20 14:40:33 +08007255 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007256 is_usb_dev = false;
7257 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
7258 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
7259 __func__, devices);
7260 }
7261
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007262 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007263
7264 if (!(is_usb_dev && may_use_hifi_record)) {
7265 if (config->sample_rate == 0)
7266 config->sample_rate = 48000;
7267 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7268 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7269 if (config->format == AUDIO_FORMAT_DEFAULT)
7270 config->format = AUDIO_FORMAT_PCM_16_BIT;
7271
7272 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
7273
7274 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
7275 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05307276 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007277
7278 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007279
7280 if (!in) {
7281 ALOGE("failed to allocate input stream");
7282 return -ENOMEM;
7283 }
7284
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307285 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307286 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7287 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007288 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007289 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007291 in->stream.common.get_sample_rate = in_get_sample_rate;
7292 in->stream.common.set_sample_rate = in_set_sample_rate;
7293 in->stream.common.get_buffer_size = in_get_buffer_size;
7294 in->stream.common.get_channels = in_get_channels;
7295 in->stream.common.get_format = in_get_format;
7296 in->stream.common.set_format = in_set_format;
7297 in->stream.common.standby = in_standby;
7298 in->stream.common.dump = in_dump;
7299 in->stream.common.set_parameters = in_set_parameters;
7300 in->stream.common.get_parameters = in_get_parameters;
7301 in->stream.common.add_audio_effect = in_add_audio_effect;
7302 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7303 in->stream.set_gain = in_set_gain;
7304 in->stream.read = in_read;
7305 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307306 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007307
7308 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007309 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007310 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007311 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007312 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007313 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007314 in->bit_width = 16;
7315 in->af_period_multiplier = 1;
7316
7317 /* Update config params with the requested sample rate and channels */
7318 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
7319 (adev->mode != AUDIO_MODE_IN_CALL)) {
7320 ret = -EINVAL;
7321 goto err_open;
7322 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007323
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007324 if (is_usb_dev && may_use_hifi_record) {
7325 /* HiFi record selects an appropriate format, channel, rate combo
7326 depending on sink capabilities*/
7327 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7328 &config->format,
7329 &in->supported_formats[0],
7330 MAX_SUPPORTED_FORMATS,
7331 &config->channel_mask,
7332 &in->supported_channel_masks[0],
7333 MAX_SUPPORTED_CHANNEL_MASKS,
7334 &config->sample_rate,
7335 &in->supported_sample_rates[0],
7336 MAX_SUPPORTED_SAMPLE_RATES);
7337 if (ret != 0) {
7338 ret = -EINVAL;
7339 goto err_open;
7340 }
7341 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007342 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307343 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05307344 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
7345 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
7346 in->config.format = PCM_FORMAT_S32_LE;
7347 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307348 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
7349 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
7350 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
7351 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7352 bool ret_error = false;
7353 in->bit_width = 24;
7354 /* 24 bit is restricted to UNPROCESSED source only,also format supported
7355 from HAL is 24_packed and 8_24
7356 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
7357 24_packed return error indicating supported format is 24_packed
7358 *> In case of any other source requesting 24 bit or float return error
7359 indicating format supported is 16 bit only.
7360
7361 on error flinger will retry with supported format passed
7362 */
7363 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
7364 (source != AUDIO_SOURCE_CAMCORDER)) {
7365 config->format = AUDIO_FORMAT_PCM_16_BIT;
7366 if (config->sample_rate > 48000)
7367 config->sample_rate = 48000;
7368 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07007369 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
7370 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307371 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
7372 ret_error = true;
7373 }
7374
7375 if (ret_error) {
7376 ret = -EINVAL;
7377 goto err_open;
7378 }
7379 }
7380
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007381 in->channel_mask = config->channel_mask;
7382 in->format = config->format;
7383
7384 in->usecase = USECASE_AUDIO_RECORD;
7385 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
7386 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
7387 is_low_latency = true;
7388#if LOW_LATENCY_CAPTURE_USE_CASE
7389 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
7390#endif
7391 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
7392 }
7393
7394 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
7395 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
7396 in->realtime = 0;
7397 in->usecase = USECASE_AUDIO_RECORD_MMAP;
7398 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07007399 in->config.format = pcm_format_from_audio_format(config->format);
Weiyin Jiangde7925e2018-11-27 18:45:53 +08007400 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007401 in->stream.start = in_start;
7402 in->stream.stop = in_stop;
7403 in->stream.create_mmap_buffer = in_create_mmap_buffer;
7404 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007405 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007406 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
7407 } else if (in->realtime) {
7408 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07007409 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007410 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007411 in->sample_rate = in->config.rate;
7412 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07007413 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007414 in->usecase = USECASE_AUDIO_RECORD_HIFI;
7415 in->config = pcm_config_audio_capture;
7416 frame_size = audio_stream_in_frame_size(&in->stream);
7417 buffer_size = get_input_buffer_size(config->sample_rate,
7418 config->format,
7419 channel_count,
7420 false /*is_low_latency*/);
7421 in->config.period_size = buffer_size / frame_size;
7422 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007423 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07007424 switch (config->format) {
7425 case AUDIO_FORMAT_PCM_32_BIT:
7426 in->bit_width = 32;
7427 break;
7428 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
7429 case AUDIO_FORMAT_PCM_8_24_BIT:
7430 in->bit_width = 24;
7431 break;
7432 default:
7433 in->bit_width = 16;
7434 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007435 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007436 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007437 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05307438 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007439 if (config->sample_rate == 0)
7440 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7441 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
7442 config->sample_rate != 8000) {
7443 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7444 ret = -EINVAL;
7445 goto err_open;
7446 }
7447 if (config->format == AUDIO_FORMAT_DEFAULT)
7448 config->format = AUDIO_FORMAT_PCM_16_BIT;
7449 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
7450 config->format = AUDIO_FORMAT_PCM_16_BIT;
7451 ret = -EINVAL;
7452 goto err_open;
7453 }
7454
7455 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
7456 in->config = pcm_config_afe_proxy_record;
7457 in->config.channels = channel_count;
7458 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307459 in->sample_rate = config->sample_rate;
Haynes Mathew George46740472017-10-27 18:40:12 -07007460 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05307461 int ret_val;
7462 pthread_mutex_lock(&adev->lock);
7463 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
7464 in, config, &channel_mask_updated);
7465 pthread_mutex_unlock(&adev->lock);
7466
7467 if (!ret_val) {
7468 if (channel_mask_updated == true) {
7469 ALOGD("%s: return error to retry with updated channel mask (%#x)",
7470 __func__, config->channel_mask);
7471 ret = -EINVAL;
7472 goto err_open;
7473 }
7474 ALOGD("%s: created multi-channel session succesfully",__func__);
7475 } else if (audio_extn_compr_cap_enabled() &&
7476 audio_extn_compr_cap_format_supported(config->format) &&
7477 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
7478 audio_extn_compr_cap_init(in);
7479 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05307480 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05307481 ret = audio_extn_cin_configure_input_stream(in);
7482 if (ret)
7483 goto err_open;
7484 } else {
7485 in->config = pcm_config_audio_capture;
7486 in->config.rate = config->sample_rate;
7487 in->config.format = pcm_format_from_audio_format(config->format);
7488 in->config.channels = channel_count;
7489 in->sample_rate = config->sample_rate;
7490 in->format = config->format;
7491 frame_size = audio_stream_in_frame_size(&in->stream);
7492 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07007493 config->format,
7494 channel_count,
7495 is_low_latency);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307496 in->config.period_size = buffer_size / frame_size;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007497
Revathi Uddarajud2634032017-12-07 14:42:34 +05307498 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
7499 /* optionally use VOIP usecase depending on config(s) */
7500 ret = adev_update_voice_comm_input_stream(in, config);
7501 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007502
Revathi Uddarajud2634032017-12-07 14:42:34 +05307503 if (ret) {
7504 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
7505 goto err_open;
7506 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007507 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007508 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307509 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7510 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007511 devices, flags, in->format,
7512 in->sample_rate, in->bit_width,
7513 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307514 register_format(in->format, in->supported_formats);
7515 register_channel_mask(in->channel_mask, in->supported_channel_masks);
7516 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307517
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007518 /* This stream could be for sound trigger lab,
7519 get sound trigger pcm if present */
7520 audio_extn_sound_trigger_check_and_get_session(in);
7521
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307522 lock_input_stream(in);
7523 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
7524 pthread_mutex_lock(&adev->lock);
7525 in->card_status = adev->card_status;
7526 pthread_mutex_unlock(&adev->lock);
7527 pthread_mutex_unlock(&in->lock);
7528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007529 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07007530 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007531 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007532
7533err_open:
7534 free(in);
7535 *stream_in = NULL;
7536 return ret;
7537}
7538
7539static void adev_close_input_stream(struct audio_hw_device *dev,
7540 struct audio_stream_in *stream)
7541{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007542 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007543 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007544 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307545
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307546 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007547
kunleizef40adb2018-12-28 17:50:23 +08007548 /* must deregister from sndmonitor first to prevent races
7549 * between the callback and close_stream
7550 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307551 audio_extn_snd_mon_unregister_listener(stream);
7552
kunleizef40adb2018-12-28 17:50:23 +08007553 /* Disable echo reference if there are no active input, hfp call
7554 * and sound trigger while closing input stream
7555 */
7556 if (!adev->active_input &&
7557 !audio_extn_hfp_is_active(adev) &&
7558 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8405edd2018-11-29 15:04:56 +08007559 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleizef40adb2018-12-28 17:50:23 +08007560 else
7561 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307562
Pallavid7c7a272018-01-16 11:22:55 +05307563 if (in == NULL) {
7564 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
7565 return;
7566 }
7567
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007568 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307569 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007570 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307571 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007572 if (ret != 0)
7573 ALOGE("%s: Compress voip input cannot be closed, error:%d",
7574 __func__, ret);
7575 } else
7576 in_standby(&stream->common);
7577
Revathi Uddarajud2634032017-12-07 14:42:34 +05307578 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07007579 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007580 audio_extn_ssr_deinit();
7581 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007582
Garmond Leunge2433c32017-09-28 21:51:22 -07007583 if (audio_extn_ffv_get_stream() == in) {
7584 audio_extn_ffv_stream_deinit();
7585 }
7586
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307587 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07007588 audio_extn_compr_cap_format_supported(in->config.format))
7589 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05307590
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307591 if (audio_extn_cin_attached_usecase(in->usecase))
7592 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007593
Mingming Yinfd7607b2016-01-22 12:48:44 -08007594 if (in->is_st_session) {
7595 ALOGV("%s: sound trigger pcm stop lab", __func__);
7596 audio_extn_sound_trigger_stop_lab(in);
7597 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007598 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307599 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007600 return;
7601}
7602
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307603int adev_create_audio_patch(struct audio_hw_device *dev,
7604 unsigned int num_sources,
7605 const struct audio_port_config *sources,
7606 unsigned int num_sinks,
7607 const struct audio_port_config *sinks,
7608 audio_patch_handle_t *handle)
7609{
7610
7611
7612 return audio_extn_hw_loopback_create_audio_patch(dev,
7613 num_sources,
7614 sources,
7615 num_sinks,
7616 sinks,
7617 handle);
7618
7619}
7620
7621int adev_release_audio_patch(struct audio_hw_device *dev,
7622 audio_patch_handle_t handle)
7623{
7624 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
7625}
7626
7627int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
7628{
7629 return audio_extn_hw_loopback_get_audio_port(dev, config);
7630}
7631
7632int adev_set_audio_port_config(struct audio_hw_device *dev,
7633 const struct audio_port_config *config)
7634{
7635 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
7636}
7637
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007638static int adev_dump(const audio_hw_device_t *device __unused,
7639 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007640{
7641 return 0;
7642}
7643
7644static int adev_close(hw_device_t *device)
7645{
7646 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07007647
7648 if (!adev)
7649 return 0;
7650
7651 pthread_mutex_lock(&adev_init_lock);
7652
7653 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307654 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007655 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08007656 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307657 audio_extn_utils_release_streams_cfg_lists(
7658 &adev->streams_output_cfg_list,
7659 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307660 if (audio_extn_qaf_is_enabled())
7661 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007662 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007663 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007664 free(adev->snd_dev_ref_cnt);
7665 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007666 if (adev->adm_deinit)
7667 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307668 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007669 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307670 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307671 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007672 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307673 if (adev->device_cfg_params) {
7674 free(adev->device_cfg_params);
7675 adev->device_cfg_params = NULL;
7676 }
Derek Chencdd17c72014-11-24 12:39:14 -08007677 if(adev->ext_hw_plugin)
7678 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Kiran Kandi910e1862013-10-29 13:29:42 -07007679 free(device);
7680 adev = NULL;
7681 }
7682 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchaa1358992018-11-14 13:25:08 +05307683 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007684 return 0;
7685}
7686
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007687/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
7688 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
7689 * just that it _might_ work.
7690 */
7691static int period_size_is_plausible_for_low_latency(int period_size)
7692{
7693 switch (period_size) {
7694 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07007695 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007696 case 240:
7697 case 320:
7698 case 480:
7699 return 1;
7700 default:
7701 return 0;
7702 }
7703}
7704
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307705static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
7706{
7707 bool is_snd_card_status = false;
7708 bool is_ext_device_status = false;
7709 char value[32];
7710 int card = -1;
7711 card_status_t status;
7712
7713 if (cookie != adev || !parms)
7714 return;
7715
7716 if (!parse_snd_card_status(parms, &card, &status)) {
7717 is_snd_card_status = true;
7718 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
7719 is_ext_device_status = true;
7720 } else {
7721 // not a valid event
7722 return;
7723 }
7724
7725 pthread_mutex_lock(&adev->lock);
7726 if (card == adev->snd_card || is_ext_device_status) {
7727 if (is_snd_card_status && adev->card_status != status) {
7728 adev->card_status = status;
7729 platform_snd_card_update(adev->platform, status);
7730 audio_extn_fm_set_parameters(adev, parms);
7731 } else if (is_ext_device_status) {
7732 platform_set_parameters(adev->platform, parms);
7733 }
7734 }
7735 pthread_mutex_unlock(&adev->lock);
7736 return;
7737}
7738
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307739/* out and adev lock held */
7740static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
7741{
7742 struct audio_usecase *uc_info;
7743 float left_p;
7744 float right_p;
7745 audio_devices_t devices;
7746
7747 uc_info = get_usecase_from_list(adev, out->usecase);
7748 if (uc_info == NULL) {
7749 ALOGE("%s: Could not find the usecase (%d) in the list",
7750 __func__, out->usecase);
7751 return -EINVAL;
7752 }
7753
7754 ALOGD("%s: enter: usecase(%d: %s)", __func__,
7755 out->usecase, use_case_table[out->usecase]);
7756
7757 if (restore) {
7758 // restore A2DP device for active usecases and unmute if required
7759 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
7760 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
7761 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
7762 select_devices(adev, uc_info->id);
7763 pthread_mutex_lock(&out->compr_mute_lock);
7764 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7765 (out->a2dp_compress_mute)) {
7766 out->a2dp_compress_mute = false;
7767 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
7768 }
7769 pthread_mutex_unlock(&out->compr_mute_lock);
7770 }
7771 } else {
7772 // mute compress stream if suspended
7773 pthread_mutex_lock(&out->compr_mute_lock);
7774 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7775 (!out->a2dp_compress_mute)) {
7776 if (!out->standby) {
7777 ALOGD("%s: selecting speaker and muting stream", __func__);
7778 devices = out->devices;
7779 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
7780 left_p = out->volume_l;
7781 right_p = out->volume_r;
7782 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7783 compress_pause(out->compr);
7784 out_set_compr_volume(&out->stream, (float)0, (float)0);
7785 out->a2dp_compress_mute = true;
7786 select_devices(adev, out->usecase);
7787 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7788 compress_resume(out->compr);
7789 out->devices = devices;
7790 out->volume_l = left_p;
7791 out->volume_r = right_p;
7792 }
7793 }
7794 pthread_mutex_unlock(&out->compr_mute_lock);
7795 }
7796 ALOGV("%s: exit", __func__);
7797 return 0;
7798}
7799
7800int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
7801{
7802 int ret = 0;
7803
7804 lock_output_stream(out);
7805 pthread_mutex_lock(&adev->lock);
7806
7807 ret = check_a2dp_restore_l(adev, out, restore);
7808
7809 pthread_mutex_unlock(&adev->lock);
7810 pthread_mutex_unlock(&out->lock);
7811 return ret;
7812}
7813
Haynes Mathew George01156f92018-04-13 15:29:54 -07007814void adev_on_battery_status_changed(bool charging)
7815{
7816 pthread_mutex_lock(&adev->lock);
7817 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
7818 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08007819 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07007820 pthread_mutex_unlock(&adev->lock);
7821}
7822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007823static int adev_open(const hw_module_t *module, const char *name,
7824 hw_device_t **device)
7825{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307826 int ret;
7827
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007828 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007829 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
7830
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007831 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07007832 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007833 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07007834 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007835 ALOGD("%s: returning existing instance of adev", __func__);
7836 ALOGD("%s: exit", __func__);
7837 pthread_mutex_unlock(&adev_init_lock);
7838 return 0;
7839 }
7840
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007841 adev = calloc(1, sizeof(struct audio_device));
7842
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007843 if (!adev) {
7844 pthread_mutex_unlock(&adev_init_lock);
7845 return -ENOMEM;
7846 }
7847
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007848 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
7849
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05307850#ifdef DYNAMIC_LOG_ENABLED
7851 register_for_dynamic_logging("hal");
7852#endif
7853
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007854 adev->device.common.tag = HARDWARE_DEVICE_TAG;
7855 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7856 adev->device.common.module = (struct hw_module_t *)module;
7857 adev->device.common.close = adev_close;
7858
7859 adev->device.init_check = adev_init_check;
7860 adev->device.set_voice_volume = adev_set_voice_volume;
7861 adev->device.set_master_volume = adev_set_master_volume;
7862 adev->device.get_master_volume = adev_get_master_volume;
7863 adev->device.set_master_mute = adev_set_master_mute;
7864 adev->device.get_master_mute = adev_get_master_mute;
7865 adev->device.set_mode = adev_set_mode;
7866 adev->device.set_mic_mute = adev_set_mic_mute;
7867 adev->device.get_mic_mute = adev_get_mic_mute;
7868 adev->device.set_parameters = adev_set_parameters;
7869 adev->device.get_parameters = adev_get_parameters;
7870 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
7871 adev->device.open_output_stream = adev_open_output_stream;
7872 adev->device.close_output_stream = adev_close_output_stream;
7873 adev->device.open_input_stream = adev_open_input_stream;
7874 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307875 adev->device.create_audio_patch = adev_create_audio_patch;
7876 adev->device.release_audio_patch = adev_release_audio_patch;
7877 adev->device.get_audio_port = adev_get_audio_port;
7878 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007879 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307880 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007881
7882 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007883 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08007884 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007885 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007886 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007887 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08007888 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07007889 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307890 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07007891 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07007892 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007893 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08007894 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08007895 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007896 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05307897 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307898 adev->perf_lock_opts[0] = 0x101;
7899 adev->perf_lock_opts[1] = 0x20E;
7900 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007901 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307902
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007903 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07007904 adev->platform = platform_init(adev);
7905 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007906 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007907 free(adev->snd_dev_ref_cnt);
7908 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007909 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07007910 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7911 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08007912 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007913 return -EINVAL;
7914 }
Eric Laurentc4aef752013-09-12 17:45:53 -07007915
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307916 if (audio_extn_qaf_is_enabled()) {
7917 ret = audio_extn_qaf_init(adev);
7918 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007919 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307920 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007921 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307922 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7923 *device = NULL;
7924 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307925 return ret;
7926 }
7927
7928 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
7929 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
7930 }
7931
Derek Chencdd17c72014-11-24 12:39:14 -08007932 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
7933
Eric Laurentc4aef752013-09-12 17:45:53 -07007934 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
7935 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
7936 if (adev->visualizer_lib == NULL) {
7937 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
7938 } else {
7939 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
7940 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007941 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007942 "visualizer_hal_start_output");
7943 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007944 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007945 "visualizer_hal_stop_output");
7946 }
7947 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05307948 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08007949 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007950 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307951 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007952 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07007953
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007954 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
7955 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
7956 if (adev->offload_effects_lib == NULL) {
7957 ALOGE("%s: DLOPEN failed for %s", __func__,
7958 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7959 } else {
7960 ALOGV("%s: DLOPEN successful for %s", __func__,
7961 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7962 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05307963 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007964 "offload_effects_bundle_hal_start_output");
7965 adev->offload_effects_stop_output =
7966 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
7967 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007968 adev->offload_effects_set_hpx_state =
7969 (int (*)(bool))dlsym(adev->offload_effects_lib,
7970 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05307971 adev->offload_effects_get_parameters =
7972 (void (*)(struct str_parms *, struct str_parms *))
7973 dlsym(adev->offload_effects_lib,
7974 "offload_effects_bundle_get_parameters");
7975 adev->offload_effects_set_parameters =
7976 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
7977 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007978 }
7979 }
7980
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007981 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
7982 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
7983 if (adev->adm_lib == NULL) {
7984 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
7985 } else {
7986 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
7987 adev->adm_init = (adm_init_t)
7988 dlsym(adev->adm_lib, "adm_init");
7989 adev->adm_deinit = (adm_deinit_t)
7990 dlsym(adev->adm_lib, "adm_deinit");
7991 adev->adm_register_input_stream = (adm_register_input_stream_t)
7992 dlsym(adev->adm_lib, "adm_register_input_stream");
7993 adev->adm_register_output_stream = (adm_register_output_stream_t)
7994 dlsym(adev->adm_lib, "adm_register_output_stream");
7995 adev->adm_deregister_stream = (adm_deregister_stream_t)
7996 dlsym(adev->adm_lib, "adm_deregister_stream");
7997 adev->adm_request_focus = (adm_request_focus_t)
7998 dlsym(adev->adm_lib, "adm_request_focus");
7999 adev->adm_abandon_focus = (adm_abandon_focus_t)
8000 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008001 adev->adm_set_config = (adm_set_config_t)
8002 dlsym(adev->adm_lib, "adm_set_config");
8003 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
8004 dlsym(adev->adm_lib, "adm_request_focus_v2");
8005 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
8006 dlsym(adev->adm_lib, "adm_is_noirq_avail");
8007 adev->adm_on_routing_change = (adm_on_routing_change_t)
8008 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008009 }
8010 }
8011
Mingming Yin514a8bc2014-07-29 15:22:21 -07008012 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008013 //initialize this to false for now,
8014 //this will be set to true through set param
8015 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07008016
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07008017 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008018 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008019 adev->dsp_bit_width_enforce_mode =
8020 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008021
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308022 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
8023 &adev->streams_output_cfg_list,
8024 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008025
Kiran Kandi910e1862013-10-29 13:29:42 -07008026 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008027
8028 char value[PROPERTY_VALUE_MAX];
8029 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008030 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008031 trial = atoi(value);
8032 if (period_size_is_plausible_for_low_latency(trial)) {
8033 pcm_config_low_latency.period_size = trial;
8034 pcm_config_low_latency.start_threshold = trial / 4;
8035 pcm_config_low_latency.avail_min = trial / 4;
8036 configured_low_latency_capture_period_size = trial;
8037 }
8038 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008039 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008040 trial = atoi(value);
8041 if (period_size_is_plausible_for_low_latency(trial)) {
8042 configured_low_latency_capture_period_size = trial;
8043 }
8044 }
8045
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08008046 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
8047
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008048 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008049 af_period_multiplier = atoi(value);
8050 if (af_period_multiplier < 0)
8051 af_period_multiplier = 2;
8052 else if (af_period_multiplier > 4)
8053 af_period_multiplier = 4;
8054
8055 ALOGV("new period_multiplier = %d", af_period_multiplier);
8056 }
8057
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008058 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008059 pthread_mutex_unlock(&adev_init_lock);
8060
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008061 if (adev->adm_init)
8062 adev->adm_data = adev->adm_init();
8063
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308064 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308065 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008066 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308067
8068 audio_extn_snd_mon_init();
8069 pthread_mutex_lock(&adev->lock);
8070 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
8071 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07008072 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
8073 /*
8074 * if the battery state callback happens before charging can be queried,
8075 * it will be guarded with the adev->lock held in the cb function and so
8076 * the callback value will reflect the latest state
8077 */
8078 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308079 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08008080 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
8081 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308082 /* Allocate memory for Device config params */
8083 adev->device_cfg_params = (struct audio_device_config_param*)
8084 calloc(platform_get_max_codec_backend(),
8085 sizeof(struct audio_device_config_param));
8086 if (adev->device_cfg_params == NULL)
8087 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308088
Eric Laurent994a6932013-07-17 11:51:42 -07008089 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008090 return 0;
8091}
8092
8093static struct hw_module_methods_t hal_module_methods = {
8094 .open = adev_open,
8095};
8096
8097struct audio_module HAL_MODULE_INFO_SYM = {
8098 .common = {
8099 .tag = HARDWARE_MODULE_TAG,
8100 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
8101 .hal_api_version = HARDWARE_HAL_API_VERSION,
8102 .id = AUDIO_HARDWARE_MODULE_ID,
8103 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08008104 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008105 .methods = &hal_module_methods,
8106 },
8107};