blob: 00d1fb804f14d3cfeeac90961135c9ebfeb4f19f [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05302 * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070066#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070068#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053077#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080080#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080081
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053082#ifdef DYNAMIC_LOG_ENABLED
83#include <log_xml_parser.h>
84#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
85#include <log_utils.h>
86#endif
87
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053089/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
90#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070092#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053093#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053094#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070095
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070096#define PROXY_OPEN_RETRY_COUNT 100
97#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080098
Mingming Yin08c7e312015-03-16 18:10:58 -070099#ifdef USE_LL_AS_PRIMARY_OUTPUT
100#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
101#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
102#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800103#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700104#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
105#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800106
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700107#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700108#define DEFAULT_VOIP_BUF_DURATION_MS 20
109#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
110#define DEFAULT_VOIP_SAMP_RATE 48000
111
112#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
113
114struct pcm_config default_pcm_config_voip_copp = {
115 .channels = 1,
116 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
117 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
118 .period_count = 2,
119 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800120 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
121 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700122};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700123
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700124#define MIN_CHANNEL_COUNT 1
125#define DEFAULT_CHANNEL_COUNT 2
126#define MAX_HIFI_CHANNEL_COUNT 8
127
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700128static unsigned int configured_low_latency_capture_period_size =
129 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
130
Haynes Mathew George16081042017-05-31 17:16:49 -0700131#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
132#define MMAP_PERIOD_COUNT_MIN 32
133#define MMAP_PERIOD_COUNT_MAX 512
134#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
135
Eric Laurentb23d5282013-05-14 15:27:20 -0700136struct pcm_config pcm_config_deep_buffer = {
137 .channels = 2,
138 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
139 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
140 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
141 .format = PCM_FORMAT_S16_LE,
142 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
143 .stop_threshold = INT_MAX,
144 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
145};
146
147struct pcm_config pcm_config_low_latency = {
148 .channels = 2,
149 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
150 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
151 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
152 .format = PCM_FORMAT_S16_LE,
153 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
154 .stop_threshold = INT_MAX,
155 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
156};
157
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700158static int af_period_multiplier = 4;
159struct pcm_config pcm_config_rt = {
160 .channels = 2,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = ULL_PERIOD_SIZE, //1 ms
163 .period_count = 512, //=> buffer size is 512ms
164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
166 .stop_threshold = INT_MAX,
167 .silence_threshold = 0,
168 .silence_size = 0,
169 .avail_min = ULL_PERIOD_SIZE, //1 ms
170};
171
Eric Laurentb23d5282013-05-14 15:27:20 -0700172struct pcm_config pcm_config_hdmi_multi = {
173 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
174 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
175 .period_size = HDMI_MULTI_PERIOD_SIZE,
176 .period_count = HDMI_MULTI_PERIOD_COUNT,
177 .format = PCM_FORMAT_S16_LE,
178 .start_threshold = 0,
179 .stop_threshold = INT_MAX,
180 .avail_min = 0,
181};
182
Haynes Mathew George16081042017-05-31 17:16:49 -0700183struct pcm_config pcm_config_mmap_playback = {
184 .channels = 2,
185 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
186 .period_size = MMAP_PERIOD_SIZE,
187 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
188 .format = PCM_FORMAT_S16_LE,
189 .start_threshold = MMAP_PERIOD_SIZE*8,
190 .stop_threshold = INT32_MAX,
191 .silence_threshold = 0,
192 .silence_size = 0,
193 .avail_min = MMAP_PERIOD_SIZE, //1 ms
194};
195
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700196struct pcm_config pcm_config_hifi = {
197 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
198 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
199 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
200 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
201 .format = PCM_FORMAT_S24_3LE,
202 .start_threshold = 0,
203 .stop_threshold = INT_MAX,
204 .avail_min = 0,
205};
206
Eric Laurentb23d5282013-05-14 15:27:20 -0700207struct pcm_config pcm_config_audio_capture = {
208 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700209 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
210 .format = PCM_FORMAT_S16_LE,
211};
212
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700213struct pcm_config pcm_config_audio_capture_rt = {
214 .channels = 2,
215 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
216 .period_size = ULL_PERIOD_SIZE,
217 .period_count = 512,
218 .format = PCM_FORMAT_S16_LE,
219 .start_threshold = 0,
220 .stop_threshold = INT_MAX,
221 .silence_threshold = 0,
222 .silence_size = 0,
223 .avail_min = ULL_PERIOD_SIZE, //1 ms
224};
225
Haynes Mathew George16081042017-05-31 17:16:49 -0700226struct pcm_config pcm_config_mmap_capture = {
227 .channels = 2,
228 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
229 .period_size = MMAP_PERIOD_SIZE,
230 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
231 .format = PCM_FORMAT_S16_LE,
232 .start_threshold = 0,
233 .stop_threshold = INT_MAX,
234 .silence_threshold = 0,
235 .silence_size = 0,
236 .avail_min = MMAP_PERIOD_SIZE, //1 ms
237};
238
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700239#define AFE_PROXY_CHANNEL_COUNT 2
240#define AFE_PROXY_SAMPLING_RATE 48000
241
242#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
243#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
244
245struct pcm_config pcm_config_afe_proxy_playback = {
246 .channels = AFE_PROXY_CHANNEL_COUNT,
247 .rate = AFE_PROXY_SAMPLING_RATE,
248 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
249 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
250 .format = PCM_FORMAT_S16_LE,
251 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
252 .stop_threshold = INT_MAX,
253 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
254};
255
256#define AFE_PROXY_RECORD_PERIOD_SIZE 768
257#define AFE_PROXY_RECORD_PERIOD_COUNT 4
258
259struct pcm_config pcm_config_afe_proxy_record = {
260 .channels = AFE_PROXY_CHANNEL_COUNT,
261 .rate = AFE_PROXY_SAMPLING_RATE,
262 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
263 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
264 .format = PCM_FORMAT_S16_LE,
265 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
266 .stop_threshold = INT_MAX,
267 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
268};
269
Ashish Jainf1eaa582016-05-23 20:54:24 +0530270#define AUDIO_MAX_PCM_FORMATS 7
271
272const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
273 [AUDIO_FORMAT_DEFAULT] = 0,
274 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
275 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
276 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
277 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
278 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
279 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
280};
281
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800282const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700283 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
284 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700285 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
286 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700287 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700288 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700289 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
290 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
291 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
292 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
293 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
294 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
295 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
296 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700297 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
298 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700299 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700300
Eric Laurentb23d5282013-05-14 15:27:20 -0700301 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700302 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530303 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
304 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
305 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530306 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
307 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700308 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700309 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700310 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700311 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700312
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800313 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800314 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700315 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700316
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700317 [USECASE_VOICE2_CALL] = "voice2-call",
318 [USECASE_VOLTE_CALL] = "volte-call",
319 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800320 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800321 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
322 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800323 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700324 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
325 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
326 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800327 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
328 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
329 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
330
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700331 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
332 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700333 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
334 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700335
336 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
337 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530338 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700339
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530340 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530341 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
342 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700343
344 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
345 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530346 /* For Interactive Audio Streams */
347 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
348 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
349 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
350 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
351 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
352 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
353 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
354 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700355
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800356 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
357
358 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback"
Eric Laurentb23d5282013-05-14 15:27:20 -0700359};
360
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700361static const audio_usecase_t offload_usecases[] = {
362 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700363 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
364 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
365 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
366 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
367 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
368 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
369 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
370 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700371};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800372
Varun Balaraje49253e2017-07-06 19:48:56 +0530373static const audio_usecase_t interactive_usecases[] = {
374 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
375 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
376 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
377 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
378 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
379 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
380 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
381 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
382};
383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800384#define STRING_TO_ENUM(string) { #string, string }
385
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800386struct string_to_enum {
387 const char *name;
388 uint32_t value;
389};
390
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700391static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800392 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800393 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
394 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
395 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700396 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800397 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
398 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800399 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700400 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
401 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
402 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
403 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
404 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
405 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
406 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
407 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
408 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
409 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
410 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800411};
412
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700413static const struct string_to_enum formats_name_to_enum_table[] = {
414 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
415 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
416 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700417 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
418 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
419 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700420 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800421 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
422 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700423 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800424};
425
426//list of all supported sample rates by HDMI specification.
427static const int out_hdmi_sample_rates[] = {
428 32000, 44100, 48000, 88200, 96000, 176400, 192000,
429};
430
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700431static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800432 STRING_TO_ENUM(32000),
433 STRING_TO_ENUM(44100),
434 STRING_TO_ENUM(48000),
435 STRING_TO_ENUM(88200),
436 STRING_TO_ENUM(96000),
437 STRING_TO_ENUM(176400),
438 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700439};
440
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700441static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700442static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700443static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700444//cache last MBDRC cal step level
445static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700446
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530447static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
448static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800449static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530450static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530451
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700452static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
453 int flags __unused)
454{
455 int dir = 0;
456 switch (uc_id) {
457 case USECASE_AUDIO_RECORD_LOW_LATENCY:
458 dir = 1;
459 case USECASE_AUDIO_PLAYBACK_ULL:
460 break;
461 default:
462 return false;
463 }
464
465 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
466 PCM_PLAYBACK : PCM_CAPTURE);
467 if (adev->adm_is_noirq_avail)
468 return adev->adm_is_noirq_avail(adev->adm_data,
469 adev->snd_card, dev_id, dir);
470 return false;
471}
472
473static void register_out_stream(struct stream_out *out)
474{
475 struct audio_device *adev = out->dev;
476 if (is_offload_usecase(out->usecase) ||
477 !adev->adm_register_output_stream)
478 return;
479
480 // register stream first for backward compatibility
481 adev->adm_register_output_stream(adev->adm_data,
482 out->handle,
483 out->flags);
484
485 if (!adev->adm_set_config)
486 return;
487
488 if (out->realtime)
489 adev->adm_set_config(adev->adm_data,
490 out->handle,
491 out->pcm, &out->config);
492}
493
494static void register_in_stream(struct stream_in *in)
495{
496 struct audio_device *adev = in->dev;
497 if (!adev->adm_register_input_stream)
498 return;
499
500 adev->adm_register_input_stream(adev->adm_data,
501 in->capture_handle,
502 in->flags);
503
504 if (!adev->adm_set_config)
505 return;
506
507 if (in->realtime)
508 adev->adm_set_config(adev->adm_data,
509 in->capture_handle,
510 in->pcm,
511 &in->config);
512}
513
514static void request_out_focus(struct stream_out *out, long ns)
515{
516 struct audio_device *adev = out->dev;
517
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700518 if (adev->adm_request_focus_v2)
519 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
520 else if (adev->adm_request_focus)
521 adev->adm_request_focus(adev->adm_data, out->handle);
522}
523
524static void request_in_focus(struct stream_in *in, long ns)
525{
526 struct audio_device *adev = in->dev;
527
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700528 if (adev->adm_request_focus_v2)
529 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
530 else if (adev->adm_request_focus)
531 adev->adm_request_focus(adev->adm_data, in->capture_handle);
532}
533
534static void release_out_focus(struct stream_out *out)
535{
536 struct audio_device *adev = out->dev;
537
538 if (adev->adm_abandon_focus)
539 adev->adm_abandon_focus(adev->adm_data, out->handle);
540}
541
542static void release_in_focus(struct stream_in *in)
543{
544 struct audio_device *adev = in->dev;
545 if (adev->adm_abandon_focus)
546 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
547}
548
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530549static int parse_snd_card_status(struct str_parms *parms, int *card,
550 card_status_t *status)
551{
552 char value[32]={0};
553 char state[32]={0};
554
555 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
556 if (ret < 0)
557 return -1;
558
559 // sscanf should be okay as value is of max length 32.
560 // same as sizeof state.
561 if (sscanf(value, "%d,%s", card, state) < 2)
562 return -1;
563
564 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
565 CARD_STATUS_OFFLINE;
566 return 0;
567}
568
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700569static inline void adjust_frames_for_device_delay(struct stream_out *out,
570 uint32_t *dsp_frames) {
571 // Adjustment accounts for A2dp encoder latency with offload usecases
572 // Note: Encoder latency is returned in ms.
573 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
574 unsigned long offset =
575 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
576 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
577 }
578}
579
vivek mehtaa76401a2015-04-24 14:12:15 -0700580__attribute__ ((visibility ("default")))
581bool audio_hw_send_gain_dep_calibration(int level) {
582 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700583 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700584
585 pthread_mutex_lock(&adev_init_lock);
586
587 if (adev != NULL && adev->platform != NULL) {
588 pthread_mutex_lock(&adev->lock);
589 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700590
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530591 // cache level info for any of the use case which
592 // was not started.
593 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700594
vivek mehtaa76401a2015-04-24 14:12:15 -0700595 pthread_mutex_unlock(&adev->lock);
596 } else {
597 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
598 }
599
600 pthread_mutex_unlock(&adev_init_lock);
601
602 return ret_val;
603}
604
Ashish Jain5106d362016-05-11 19:23:33 +0530605static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
606{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800607 bool gapless_enabled = false;
608 const char *mixer_ctl_name = "Compress Gapless Playback";
609 struct mixer_ctl *ctl;
610
611 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700612 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530613
614 /*Disable gapless if its AV playback*/
615 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800616
617 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
618 if (!ctl) {
619 ALOGE("%s: Could not get ctl for mixer cmd - %s",
620 __func__, mixer_ctl_name);
621 return -EINVAL;
622 }
623
624 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
625 ALOGE("%s: Could not set gapless mode %d",
626 __func__, gapless_enabled);
627 return -EINVAL;
628 }
629 return 0;
630}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700631
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700632__attribute__ ((visibility ("default")))
633int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
634 int table_size) {
635 int ret_val = 0;
636 ALOGV("%s: enter ... ", __func__);
637
638 pthread_mutex_lock(&adev_init_lock);
639 if (adev == NULL) {
640 ALOGW("%s: adev is NULL .... ", __func__);
641 goto done;
642 }
643
644 pthread_mutex_lock(&adev->lock);
645 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
646 pthread_mutex_unlock(&adev->lock);
647done:
648 pthread_mutex_unlock(&adev_init_lock);
649 ALOGV("%s: exit ... ", __func__);
650 return ret_val;
651}
652
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700653static bool is_supported_format(audio_format_t format)
654{
Eric Laurent86e17132013-09-12 17:49:30 -0700655 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530656 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530657 format == AUDIO_FORMAT_AAC_LC ||
658 format == AUDIO_FORMAT_AAC_HE_V1 ||
659 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530660 format == AUDIO_FORMAT_AAC_ADTS_LC ||
661 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
662 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530663 format == AUDIO_FORMAT_AAC_LATM_LC ||
664 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
665 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530666 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
667 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530668 format == AUDIO_FORMAT_PCM_FLOAT ||
669 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700670 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530671 format == AUDIO_FORMAT_AC3 ||
672 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700673 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530674 format == AUDIO_FORMAT_DTS ||
675 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800676 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530677 format == AUDIO_FORMAT_ALAC ||
678 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530679 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530680 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800681 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530682 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700683 format == AUDIO_FORMAT_APTX ||
684 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800685 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700686
687 return false;
688}
689
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700690static inline bool is_mmap_usecase(audio_usecase_t uc_id)
691{
692 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
693 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
694}
695
Avinash Vaish71a8b972014-07-24 15:36:33 +0530696static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
697 struct audio_usecase *uc_info)
698{
699 struct listnode *node;
700 struct audio_usecase *usecase;
701
702 if (uc_info == NULL)
703 return -EINVAL;
704
705 /* Re-route all voice usecases on the shared backend other than the
706 specified usecase to new snd devices */
707 list_for_each(node, &adev->usecase_list) {
708 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800709 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530710 enable_audio_route(adev, usecase);
711 }
712 return 0;
713}
714
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530715static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530716{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530717 ALOGV("%s", __func__);
718 audio_route_apply_and_update_path(adev->audio_route,
719 "asrc-mode");
720 adev->asrc_mode_enabled = true;
721}
722
723static void disable_asrc_mode(struct audio_device *adev)
724{
725 ALOGV("%s", __func__);
726 audio_route_reset_and_update_path(adev->audio_route,
727 "asrc-mode");
728 adev->asrc_mode_enabled = false;
729}
730
731/*
732 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
733 * 44.1 or Native DSD backends are enabled for any of current use case.
734 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
735 * - Disable current mix path use case(Headphone backend) and re-enable it with
736 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
737 * e.g. Naitve DSD or Headphone 44.1 -> + 48
738 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530739static void check_and_set_asrc_mode(struct audio_device *adev,
740 struct audio_usecase *uc_info,
741 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530742{
743 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530744 int i, num_new_devices = 0;
745 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
746 /*
747 *Split snd device for new combo use case
748 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
749 */
750 if (platform_split_snd_device(adev->platform,
751 snd_device,
752 &num_new_devices,
753 split_new_snd_devices) == 0) {
754 for (i = 0; i < num_new_devices; i++)
755 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
756 } else {
757 int new_backend_idx = platform_get_backend_index(snd_device);
758 if (((new_backend_idx == HEADPHONE_BACKEND) ||
759 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
760 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
761 !adev->asrc_mode_enabled) {
762 struct listnode *node = NULL;
763 struct audio_usecase *uc = NULL;
764 struct stream_out *curr_out = NULL;
765 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
766 int i, num_devices, ret = 0;
767 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530768
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530769 list_for_each(node, &adev->usecase_list) {
770 uc = node_to_item(node, struct audio_usecase, list);
771 curr_out = (struct stream_out*) uc->stream.out;
772 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
773 /*
774 *Split snd device for existing combo use case
775 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
776 */
777 ret = platform_split_snd_device(adev->platform,
778 uc->out_snd_device,
779 &num_devices,
780 split_snd_devices);
781 if (ret < 0 || num_devices == 0) {
782 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
783 split_snd_devices[0] = uc->out_snd_device;
784 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800785 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530786 for (i = 0; i < num_devices; i++) {
787 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
788 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
789 if((new_backend_idx == HEADPHONE_BACKEND) &&
790 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
791 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
792 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
793 __func__);
794 enable_asrc_mode(adev);
795 break;
796 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
797 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
798 (usecase_backend_idx == HEADPHONE_BACKEND)) {
799 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
800 __func__);
801 disable_audio_route(adev, uc);
802 disable_snd_device(adev, uc->out_snd_device);
803 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
804 if (new_backend_idx == DSD_NATIVE_BACKEND)
805 audio_route_apply_and_update_path(adev->audio_route,
806 "hph-true-highquality-mode");
807 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
808 (curr_out->bit_width >= 24))
809 audio_route_apply_and_update_path(adev->audio_route,
810 "hph-highquality-mode");
811 enable_asrc_mode(adev);
812 enable_snd_device(adev, uc->out_snd_device);
813 enable_audio_route(adev, uc);
814 break;
815 }
816 }
817 // reset split devices count
818 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800819 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530820 if (adev->asrc_mode_enabled)
821 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530822 }
823 }
824 }
825}
826
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700827#ifdef DYNAMIC_ECNS_ENABLED
828static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
829 struct audio_effect_config effect_config,
830 unsigned int param_value)
831{
832 char mixer_ctl_name[] = "Audio Effect";
833 struct mixer_ctl *ctl;
834 long set_values[6];
835 struct stream_in *in = adev->active_input;
836
837 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
838 if (!ctl) {
839 ALOGE("%s: Could not get mixer ctl - %s",
840 __func__, mixer_ctl_name);
841 return -EINVAL;
842 }
843
844 set_values[0] = 1; //0:Rx 1:Tx
845 set_values[1] = in->app_type_cfg.app_type;
846 set_values[2] = (long)effect_config.module_id;
847 set_values[3] = (long)effect_config.instance_id;
848 set_values[4] = (long)effect_config.param_id;
849 set_values[5] = param_value;
850
851 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
852
853 return 0;
854
855}
856
857static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
858 int effect_type, unsigned int *param_value)
859{
860 int ret = 0;
861 struct audio_effect_config other_effect_config;
862 struct audio_usecase *usecase = NULL;
863 struct stream_in *in = adev->active_input;
864
865 usecase = get_usecase_from_list(adev, in->usecase);
866 if (!usecase)
867 return -EINVAL;
868
869 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
870 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
871 if (ret < 0) {
872 ALOGE("%s Failed to get effect params %d", __func__, ret);
873 return ret;
874 }
875
876 if (module_id == other_effect_config.module_id) {
877 //Same module id for AEC/NS. Values need to be combined
878 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
879 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
880 *param_value |= other_effect_config.param_value;
881 }
882 }
883
884 return ret;
885}
886
887static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
888{
889 struct audio_effect_config effect_config;
890 struct audio_usecase *usecase = NULL;
891 int ret = 0;
892 unsigned int param_value = 0;
893 struct stream_in *in = adev->active_input;
894
895 if (!in) {
896 ALOGE("%s: Invalid input stream", __func__);
897 return -EINVAL;
898 }
899
900 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
901
902 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800903 if (usecase == NULL) {
904 ALOGE("%s: Could not find the usecase (%d) in the list",
905 __func__, in->usecase);
906 return -EINVAL;
907 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700908
909 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
910 if (ret < 0) {
911 ALOGE("%s Failed to get module id %d", __func__, ret);
912 return ret;
913 }
914 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
915 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
916
917 if(enable)
918 param_value = effect_config.param_value;
919
920 /*Special handling for AEC & NS effects Param values need to be
921 updated if module ids are same*/
922
923 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
924 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
925 if (ret < 0)
926 return ret;
927 }
928
929 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
930
931 return ret;
932}
933
934static void check_and_enable_effect(struct audio_device *adev)
935{
936
937 if (adev->active_input->enable_aec) {
938 enable_disable_effect(adev, EFFECT_AEC, true);
939 }
940
941 if (adev->active_input->enable_ns &&
942 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
943 enable_disable_effect(adev, EFFECT_NS, true);
944 }
945}
946#else
947#define enable_disable_effect(x, y, z) ENOSYS
948#define check_and_enable_effect(x) ENOSYS
949#endif
950
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700951int pcm_ioctl(struct pcm *pcm, int request, ...)
952{
953 va_list ap;
954 void * arg;
955 int pcm_fd = *(int*)pcm;
956
957 va_start(ap, request);
958 arg = va_arg(ap, void *);
959 va_end(ap);
960
961 return ioctl(pcm_fd, request, arg);
962}
963
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700964int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700965 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800966{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700967 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700968 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530969 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800970
971 if (usecase == NULL)
972 return -EINVAL;
973
974 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
975
Surendar Karka93cd25a2018-08-28 14:21:37 +0530976 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700977 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800978 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800980
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800981#ifdef DS1_DOLBY_DAP_ENABLED
982 audio_extn_dolby_set_dmid(adev);
983 audio_extn_dolby_set_endpoint(adev);
984#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700985 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700986 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530987 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700988 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530989 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530990 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
991 out = usecase->stream.out;
992 if (out && out->compr)
993 audio_extn_utils_compress_set_clk_rec_mode(usecase);
994 }
995
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800996 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700997 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700998 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700999 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001000 ALOGV("%s: exit", __func__);
1001 return 0;
1002}
1003
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001004int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001005 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001006{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001007 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001008 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001009
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301010 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001011 return -EINVAL;
1012
1013 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301014 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001015 snd_device = usecase->in_snd_device;
1016 else
1017 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001018 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001019 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001020 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001021 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001022 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301023 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024 ALOGV("%s: exit", __func__);
1025 return 0;
1026}
1027
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001028int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001029 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001030{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301031 int i, num_devices = 0;
1032 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001033 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1034
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001035 if (snd_device < SND_DEVICE_MIN ||
1036 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001037 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001038 return -EINVAL;
1039 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001040
1041 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001042
1043 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
1044 ALOGE("%s: Invalid sound device returned", __func__);
1045 return -EINVAL;
1046 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001047 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -07001048 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001049 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001050 return 0;
1051 }
1052
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301053
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001054 if (audio_extn_spkr_prot_is_enabled())
1055 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001056
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001057 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1058 audio_extn_spkr_prot_is_enabled()) {
1059 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001060 adev->snd_dev_ref_cnt[snd_device]--;
1061 return -EINVAL;
1062 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001063 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001064 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001065 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001066 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001067 return -EINVAL;
1068 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001069 } else if (platform_split_snd_device(adev->platform,
1070 snd_device,
1071 &num_devices,
1072 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301073 for (i = 0; i < num_devices; i++) {
1074 enable_snd_device(adev, new_snd_devices[i]);
1075 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001076 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001077 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301078
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301079
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301080 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1081 (audio_extn_a2dp_start_playback() < 0)) {
1082 ALOGE(" fail to configure A2dp control path ");
1083 return -EINVAL;
1084 }
1085
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001086 /* due to the possibility of calibration overwrite between listen
1087 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001088 audio_extn_sound_trigger_update_device_status(snd_device,
1089 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301090 audio_extn_listen_update_device_status(snd_device,
1091 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001092 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001093 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001094 audio_extn_sound_trigger_update_device_status(snd_device,
1095 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301096 audio_extn_listen_update_device_status(snd_device,
1097 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001098 return -EINVAL;
1099 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001100 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001101 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301102
1103 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1104 !adev->native_playback_enabled &&
1105 audio_is_true_native_stream_active(adev)) {
1106 ALOGD("%s: %d: napb: enabling native mode in hardware",
1107 __func__, __LINE__);
1108 audio_route_apply_and_update_path(adev->audio_route,
1109 "true-native-mode");
1110 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301111 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301112 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1113 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001114 (audio_extn_ffv_get_stream() == adev->active_input)) {
1115 ALOGD("%s: init ec ref loopback", __func__);
1116 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1117 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001118 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001119 return 0;
1120}
1121
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001122int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001123 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001124{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301125 int i, num_devices = 0;
1126 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001127 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1128
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001129 if (snd_device < SND_DEVICE_MIN ||
1130 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001131 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001132 return -EINVAL;
1133 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1135 ALOGE("%s: device ref cnt is already 0", __func__);
1136 return -EINVAL;
1137 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001138
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001139 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001140
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001141 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1142 ALOGE("%s: Invalid sound device returned", __func__);
1143 return -EINVAL;
1144 }
1145
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001146 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001147 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301148
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001149 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1150 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001151 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001152
1153 // when speaker device is disabled, reset swap.
1154 // will be renabled on usecase start
1155 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001156 } else if (platform_split_snd_device(adev->platform,
1157 snd_device,
1158 &num_devices,
1159 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301160 for (i = 0; i < num_devices; i++) {
1161 disable_snd_device(adev, new_snd_devices[i]);
1162 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001163 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001164 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001165 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001166
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301167 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1168 audio_extn_a2dp_stop_playback();
1169
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001170 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301171 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301172 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1173 adev->native_playback_enabled) {
1174 ALOGD("%s: %d: napb: disabling native mode in hardware",
1175 __func__, __LINE__);
1176 audio_route_reset_and_update_path(adev->audio_route,
1177 "true-native-mode");
1178 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301179 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1180 adev->asrc_mode_enabled) {
1181 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301182 disable_asrc_mode(adev);
1183 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301184 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001185 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1186 (audio_extn_ffv_get_stream() == adev->active_input)) {
1187 ALOGD("%s: deinit ec ref loopback", __func__);
1188 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1189 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001190 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001191 audio_extn_sound_trigger_update_device_status(snd_device,
1192 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301193 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001194 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001195 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001196
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001197 return 0;
1198}
1199
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001200/*
1201 legend:
1202 uc - existing usecase
1203 new_uc - new usecase
1204 d1, d11, d2 - SND_DEVICE enums
1205 a1, a2 - corresponding ANDROID device enums
1206 B1, B2 - backend strings
1207
1208case 1
1209 uc->dev d1 (a1) B1
1210 new_uc->dev d1 (a1), d2 (a2) B1, B2
1211
1212 resolution: disable and enable uc->dev on d1
1213
1214case 2
1215 uc->dev d1 (a1) B1
1216 new_uc->dev d11 (a1) B1
1217
1218 resolution: need to switch uc since d1 and d11 are related
1219 (e.g. speaker and voice-speaker)
1220 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1221
1222case 3
1223 uc->dev d1 (a1) B1
1224 new_uc->dev d2 (a2) B2
1225
1226 resolution: no need to switch uc
1227
1228case 4
1229 uc->dev d1 (a1) B1
1230 new_uc->dev d2 (a2) B1
1231
1232 resolution: disable enable uc-dev on d2 since backends match
1233 we cannot enable two streams on two different devices if they
1234 share the same backend. e.g. if offload is on speaker device using
1235 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1236 using the same backend, offload must also be switched to voice-handset.
1237
1238case 5
1239 uc->dev d1 (a1) B1
1240 new_uc->dev d1 (a1), d2 (a2) B1
1241
1242 resolution: disable enable uc-dev on d2 since backends match
1243 we cannot enable two streams on two different devices if they
1244 share the same backend.
1245
1246case 6
1247 uc->dev d1 (a1) B1
1248 new_uc->dev d2 (a1) B2
1249
1250 resolution: no need to switch
1251
1252case 7
1253 uc->dev d1 (a1), d2 (a2) B1, B2
1254 new_uc->dev d1 (a1) B1
1255
1256 resolution: no need to switch
1257
Zhou Song4ba65882018-07-09 14:48:07 +08001258case 8
1259 uc->dev d1 (a1) B1
1260 new_uc->dev d11 (a1), d2 (a2) B1, B2
1261 resolution: compared to case 1, for this case, d1 and d11 are related
1262 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001263*/
1264static snd_device_t derive_playback_snd_device(void * platform,
1265 struct audio_usecase *uc,
1266 struct audio_usecase *new_uc,
1267 snd_device_t new_snd_device)
1268{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301269 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001270
1271 snd_device_t d1 = uc->out_snd_device;
1272 snd_device_t d2 = new_snd_device;
1273
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301274 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301275 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301276 a1 = uc->stream.inout->out_config.devices;
1277 a2 = new_uc->stream.inout->out_config.devices;
1278 break;
1279 default :
1280 a1 = uc->stream.out->devices;
1281 a2 = new_uc->stream.out->devices;
1282 break;
1283 }
1284
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001285 // Treat as a special case when a1 and a2 are not disjoint
1286 if ((a1 != a2) && (a1 & a2)) {
1287 snd_device_t d3[2];
1288 int num_devices = 0;
1289 int ret = platform_split_snd_device(platform,
1290 popcount(a1) > 1 ? d1 : d2,
1291 &num_devices,
1292 d3);
1293 if (ret < 0) {
1294 if (ret != -ENOSYS) {
1295 ALOGW("%s failed to split snd_device %d",
1296 __func__,
1297 popcount(a1) > 1 ? d1 : d2);
1298 }
1299 goto end;
1300 }
1301
1302 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1303 // But if it does happen, we need to give priority to d2 if
1304 // the combo devices active on the existing usecase share a backend.
1305 // This is because we cannot have a usecase active on a combo device
1306 // and a new usecase requests one device in this combo pair.
1307 if (platform_check_backends_match(d3[0], d3[1])) {
1308 return d2; // case 5
1309 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001310 // check if d1 is related to any of d3's
1311 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001312 return d1; // case 1
1313 else
1314 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001315 }
1316 } else {
1317 if (platform_check_backends_match(d1, d2)) {
1318 return d2; // case 2, 4
1319 } else {
1320 return d1; // case 6, 3
1321 }
1322 }
1323
1324end:
1325 return d2; // return whatever was calculated before.
1326}
1327
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001328static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301329 struct audio_usecase *uc_info,
1330 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001331{
1332 struct listnode *node;
1333 struct audio_usecase *usecase;
1334 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301335 snd_device_t uc_derive_snd_device;
1336 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001337 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001338 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301339 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001340 /*
1341 * This function is to make sure that all the usecases that are active on
1342 * the hardware codec backend are always routed to any one device that is
1343 * handled by the hardware codec.
1344 * For example, if low-latency and deep-buffer usecases are currently active
1345 * on speaker and out_set_parameters(headset) is received on low-latency
1346 * output, then we have to make sure deep-buffer is also switched to headset,
1347 * because of the limitation that both the devices cannot be enabled
1348 * at the same time as they share the same backend.
1349 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001350 /*
1351 * This call is to check if we need to force routing for a particular stream
1352 * If there is a backend configuration change for the device when a
1353 * new stream starts, then ADM needs to be closed and re-opened with the new
1354 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001355 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001356 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001357 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1358 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301359 /* For a2dp device reconfigure all active sessions
1360 * with new AFE encoder format based on a2dp state
1361 */
1362 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1363 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1364 audio_extn_a2dp_is_force_device_switch()) {
1365 force_routing = true;
1366 force_restart_session = true;
1367 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301368 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1369
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001370 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001371 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001372 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001373 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1374 switch_device[i] = false;
1375
1376 list_for_each(node, &adev->usecase_list) {
1377 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001378
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301379 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1380 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301381 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301382 platform_get_snd_device_name(usecase->out_snd_device),
1383 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301384 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1385 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1386 usecase, uc_info, snd_device);
1387 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1388 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1389 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1390 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001391 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301392 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1393 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1394 ((force_restart_session) ||
1395 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301396 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1397 __func__, use_case_table[usecase->id],
1398 platform_get_snd_device_name(usecase->out_snd_device));
1399 disable_audio_route(adev, usecase);
1400 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301401 /* Enable existing usecase on derived playback device */
1402 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301403 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301404 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001405 }
1406 }
1407
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301408 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1409 num_uc_to_switch);
1410
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001411 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001412 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001413
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301414 /* Make sure the previous devices to be disabled first and then enable the
1415 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001416 list_for_each(node, &adev->usecase_list) {
1417 usecase = node_to_item(node, struct audio_usecase, list);
1418 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001419 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001420 }
1421 }
1422
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001423 list_for_each(node, &adev->usecase_list) {
1424 usecase = node_to_item(node, struct audio_usecase, list);
1425 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301426 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001427 }
1428 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001429
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001430 /* Re-route all the usecases on the shared backend other than the
1431 specified usecase to new snd devices */
1432 list_for_each(node, &adev->usecase_list) {
1433 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301434 /* Update the out_snd_device only before enabling the audio route */
1435 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301436 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301437 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301438 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301439 use_case_table[usecase->id],
1440 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001441 /* Update voc calibration before enabling VoIP route */
1442 if (usecase->type == VOIP_CALL)
1443 status = platform_switch_voice_call_device_post(adev->platform,
1444 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001445 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301446 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001447 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1448 out_set_voip_volume(&usecase->stream.out->stream,
1449 usecase->stream.out->volume_l,
1450 usecase->stream.out->volume_r);
1451 }
Yidong Huang7939a3b2018-01-23 17:32:30 +08001452 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1453 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1454 if (parms)
1455 audio_extn_fm_set_parameters(adev, parms);
1456 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301457 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001458 }
1459 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001460 }
1461}
1462
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301463static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001464 struct audio_usecase *uc_info,
1465 snd_device_t snd_device)
1466{
1467 struct listnode *node;
1468 struct audio_usecase *usecase;
1469 bool switch_device[AUDIO_USECASE_MAX];
1470 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301471 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001472 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001473
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301474 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1475 snd_device);
1476 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301477
1478 /*
1479 * Make sure out devices is checked against out codec backend device and
1480 * also in devices against in codec backend. Checking out device against in
1481 * codec backend or vice versa causes issues.
1482 */
1483 if (uc_info->type == PCM_CAPTURE)
1484 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001485 /*
1486 * This function is to make sure that all the active capture usecases
1487 * are always routed to the same input sound device.
1488 * For example, if audio-record and voice-call usecases are currently
1489 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1490 * is received for voice call then we have to make sure that audio-record
1491 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1492 * because of the limitation that two devices cannot be enabled
1493 * at the same time if they share the same backend.
1494 */
1495 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1496 switch_device[i] = false;
1497
1498 list_for_each(node, &adev->usecase_list) {
1499 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301500 /*
1501 * TODO: Enhance below condition to handle BT sco/USB multi recording
1502 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001503 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001504 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301505 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301506 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301507 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301508 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001509 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001510 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1511 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001512 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001513 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001514 switch_device[usecase->id] = true;
1515 num_uc_to_switch++;
1516 }
1517 }
1518
1519 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001520 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001521
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301522 /* Make sure the previous devices to be disabled first and then enable the
1523 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001524 list_for_each(node, &adev->usecase_list) {
1525 usecase = node_to_item(node, struct audio_usecase, list);
1526 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001527 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001528 }
1529 }
1530
1531 list_for_each(node, &adev->usecase_list) {
1532 usecase = node_to_item(node, struct audio_usecase, list);
1533 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001534 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001535 }
1536 }
1537
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001538 /* Re-route all the usecases on the shared backend other than the
1539 specified usecase to new snd devices */
1540 list_for_each(node, &adev->usecase_list) {
1541 usecase = node_to_item(node, struct audio_usecase, list);
1542 /* Update the in_snd_device only before enabling the audio route */
1543 if (switch_device[usecase->id] ) {
1544 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001545 if (usecase->type != VOICE_CALL) {
1546 /* Update voc calibration before enabling VoIP route */
1547 if (usecase->type == VOIP_CALL)
1548 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001549 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001550 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301551 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001552 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001553 }
1554 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001555 }
1556}
1557
Mingming Yin3a941d42016-02-17 18:08:05 -08001558static void reset_hdmi_sink_caps(struct stream_out *out) {
1559 int i = 0;
1560
1561 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1562 out->supported_channel_masks[i] = 0;
1563 }
1564 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1565 out->supported_formats[i] = 0;
1566 }
1567 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1568 out->supported_sample_rates[i] = 0;
1569 }
1570}
1571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001572/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001573static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001574{
Mingming Yin3a941d42016-02-17 18:08:05 -08001575 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001576 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001577
Mingming Yin3a941d42016-02-17 18:08:05 -08001578 reset_hdmi_sink_caps(out);
1579
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001580 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001581 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001582 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001583 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001584 }
1585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001587 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001588 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001589 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001590 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1591 case 6:
1592 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1593 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1594 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1595 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1596 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1597 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001598 break;
1599 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001600 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001601 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001602 break;
1603 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001604
1605 // check channel format caps
1606 i = 0;
1607 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1608 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1609 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1610 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1611 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1612 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1613 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1614 }
1615
Ben Romberger1aaaf862017-04-06 17:49:46 -07001616 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1617 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1618 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1619 }
1620
Mingming Yin3a941d42016-02-17 18:08:05 -08001621 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1622 ALOGV(":%s HDMI supports DTS format", __func__);
1623 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1624 }
1625
1626 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1627 ALOGV(":%s HDMI supports DTS HD format", __func__);
1628 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1629 }
1630
Naresh Tanniru928f0862017-04-07 16:44:23 -07001631 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1632 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1633 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1634 }
1635
Mingming Yin3a941d42016-02-17 18:08:05 -08001636
1637 // check sample rate caps
1638 i = 0;
1639 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1640 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1641 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1642 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1643 }
1644 }
1645
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001646 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001647}
1648
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001649static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1650 uint32_t *supported_sample_rates __unused,
1651 uint32_t max_rates __unused)
1652{
1653 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1654 supported_sample_rates,
1655 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301656 ssize_t i = 0;
1657
1658 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001659 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1660 supported_sample_rates[i]);
1661 }
1662 return count;
1663}
1664
1665static inline int read_usb_sup_channel_masks(bool is_playback,
1666 audio_channel_mask_t *supported_channel_masks,
1667 uint32_t max_masks)
1668{
1669 int channels = audio_extn_usb_get_max_channels(is_playback);
1670 int channel_count;
1671 uint32_t num_masks = 0;
1672 if (channels > MAX_HIFI_CHANNEL_COUNT)
1673 channels = MAX_HIFI_CHANNEL_COUNT;
1674
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301675 channel_count = DEFAULT_CHANNEL_COUNT;
1676
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001677 if (is_playback) {
1678 // For playback we never report mono because the framework always outputs stereo
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001679 // audio_channel_out_mask_from_count() does return positional masks for channel counts
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301680 // above 2 but we want indexed masks here.
1681 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001682 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001683 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1684 // indexed mask
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301685 supported_channel_masks[num_masks++] = audio_channel_in_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001686 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301687
1688 for (channel_count = channels; ((channel_count >= DEFAULT_CHANNEL_COUNT) &&
1689 (num_masks < max_masks)); channel_count--) {
1690 supported_channel_masks[num_masks++] =
1691 audio_channel_mask_for_index_assignment_from_count(channel_count);
1692 }
1693
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001694 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1695 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1696 return num_masks;
1697}
1698
1699static inline int read_usb_sup_formats(bool is_playback __unused,
1700 audio_format_t *supported_formats,
1701 uint32_t max_formats __unused)
1702{
1703 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1704 switch (bitwidth) {
1705 case 24:
1706 // XXX : usb.c returns 24 for s24 and s24_le?
1707 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1708 break;
1709 case 32:
1710 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1711 break;
1712 case 16:
1713 default :
1714 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1715 break;
1716 }
1717 ALOGV("%s: %s supported format %d", __func__,
1718 is_playback ? "P" : "C", bitwidth);
1719 return 1;
1720}
1721
1722static inline int read_usb_sup_params_and_compare(bool is_playback,
1723 audio_format_t *format,
1724 audio_format_t *supported_formats,
1725 uint32_t max_formats,
1726 audio_channel_mask_t *mask,
1727 audio_channel_mask_t *supported_channel_masks,
1728 uint32_t max_masks,
1729 uint32_t *rate,
1730 uint32_t *supported_sample_rates,
1731 uint32_t max_rates) {
1732 int ret = 0;
1733 int num_formats;
1734 int num_masks;
1735 int num_rates;
1736 int i;
1737
1738 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1739 max_formats);
1740 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1741 max_masks);
1742
1743 num_rates = read_usb_sup_sample_rates(is_playback,
1744 supported_sample_rates, max_rates);
1745
1746#define LUT(table, len, what, dflt) \
1747 for (i=0; i<len && (table[i] != what); i++); \
1748 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1749
1750 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1751 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1752 LUT(supported_sample_rates, num_rates, *rate, 0);
1753
1754#undef LUT
1755 return ret < 0 ? -EINVAL : 0; // HACK TBD
1756}
1757
Alexy Josephb1379942016-01-29 15:49:38 -08001758audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001759 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001760{
1761 struct audio_usecase *usecase;
1762 struct listnode *node;
1763
1764 list_for_each(node, &adev->usecase_list) {
1765 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001766 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001767 ALOGV("%s: usecase id %d", __func__, usecase->id);
1768 return usecase->id;
1769 }
1770 }
1771 return USECASE_INVALID;
1772}
1773
Alexy Josephb1379942016-01-29 15:49:38 -08001774struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001775 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001776{
1777 struct audio_usecase *usecase;
1778 struct listnode *node;
1779
1780 list_for_each(node, &adev->usecase_list) {
1781 usecase = node_to_item(node, struct audio_usecase, list);
1782 if (usecase->id == uc_id)
1783 return usecase;
1784 }
1785 return NULL;
1786}
1787
Dhananjay Kumard4833242016-10-06 22:09:12 +05301788struct stream_in *get_next_active_input(const struct audio_device *adev)
1789{
1790 struct audio_usecase *usecase;
1791 struct listnode *node;
1792
1793 list_for_each_reverse(node, &adev->usecase_list) {
1794 usecase = node_to_item(node, struct audio_usecase, list);
1795 if (usecase->type == PCM_CAPTURE)
1796 return usecase->stream.in;
1797 }
1798 return NULL;
1799}
1800
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301801/*
1802 * is a true native playback active
1803 */
1804bool audio_is_true_native_stream_active(struct audio_device *adev)
1805{
1806 bool active = false;
1807 int i = 0;
1808 struct listnode *node;
1809
1810 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1811 ALOGV("%s:napb: not in true mode or non hdphones device",
1812 __func__);
1813 active = false;
1814 goto exit;
1815 }
1816
1817 list_for_each(node, &adev->usecase_list) {
1818 struct audio_usecase *uc;
1819 uc = node_to_item(node, struct audio_usecase, list);
1820 struct stream_out *curr_out =
1821 (struct stream_out*) uc->stream.out;
1822
1823 if (curr_out && PCM_PLAYBACK == uc->type) {
1824 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1825 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1826 uc->id, curr_out->sample_rate,
1827 curr_out->bit_width,
1828 platform_get_snd_device_name(uc->out_snd_device));
1829
1830 if (is_offload_usecase(uc->id) &&
1831 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1832 active = true;
1833 ALOGD("%s:napb:native stream detected", __func__);
1834 }
1835 }
1836 }
1837exit:
1838 return active;
1839}
1840
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001841uint32_t adev_get_dsp_bit_width_enforce_mode()
1842{
1843 if (adev == NULL) {
1844 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1845 return 0;
1846 }
1847 return adev->dsp_bit_width_enforce_mode;
1848}
1849
1850static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1851{
1852 char value[PROPERTY_VALUE_MAX];
1853 int trial;
1854 uint32_t dsp_bit_width_enforce_mode = 0;
1855
1856 if (!mixer) {
1857 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1858 __func__);
1859 return 0;
1860 }
1861
1862 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1863 value, NULL) > 0) {
1864 trial = atoi(value);
1865 switch (trial) {
1866 case 16:
1867 dsp_bit_width_enforce_mode = 16;
1868 break;
1869 case 24:
1870 dsp_bit_width_enforce_mode = 24;
1871 break;
1872 case 32:
1873 dsp_bit_width_enforce_mode = 32;
1874 break;
1875 default:
1876 dsp_bit_width_enforce_mode = 0;
1877 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1878 break;
1879 }
1880 }
1881
1882 return dsp_bit_width_enforce_mode;
1883}
1884
1885static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1886 uint32_t enforce_mode,
1887 bool enable)
1888{
1889 struct mixer_ctl *ctl = NULL;
1890 const char *mixer_ctl_name = "ASM Bit Width";
1891 uint32_t asm_bit_width_mode = 0;
1892
1893 if (enforce_mode == 0) {
1894 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1895 return;
1896 }
1897
1898 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1899 if (!ctl) {
1900 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1901 __func__, mixer_ctl_name);
1902 return;
1903 }
1904
1905 if (enable)
1906 asm_bit_width_mode = enforce_mode;
1907 else
1908 asm_bit_width_mode = 0;
1909
1910 ALOGV("%s DSP bit width feature status is %d width=%d",
1911 __func__, enable, asm_bit_width_mode);
1912 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1913 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1914 asm_bit_width_mode);
1915
1916 return;
1917}
1918
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301919/*
1920 * if native DSD playback active
1921 */
1922bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1923{
1924 bool active = false;
1925 struct listnode *node = NULL;
1926 struct audio_usecase *uc = NULL;
1927 struct stream_out *curr_out = NULL;
1928
1929 list_for_each(node, &adev->usecase_list) {
1930 uc = node_to_item(node, struct audio_usecase, list);
1931 curr_out = (struct stream_out*) uc->stream.out;
1932
1933 if (curr_out && PCM_PLAYBACK == uc->type &&
1934 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1935 active = true;
1936 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301937 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301938 }
1939 }
1940 return active;
1941}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301942
1943static bool force_device_switch(struct audio_usecase *usecase)
1944{
1945 bool ret = false;
1946 bool is_it_true_mode = false;
1947
Zhou Song30f2c3e2018-02-08 14:02:15 +08001948 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05301949 usecase->type == TRANSCODE_LOOPBACK_RX ||
1950 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08001951 return false;
1952 }
1953
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001954 if(usecase->stream.out == NULL) {
1955 ALOGE("%s: stream.out is NULL", __func__);
1956 return false;
1957 }
1958
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301959 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001960 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1961 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1962 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301963 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1964 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1965 (!is_it_true_mode && adev->native_playback_enabled)){
1966 ret = true;
1967 ALOGD("napb: time to toggle native mode");
1968 }
1969 }
1970
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301971 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301972 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1973 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001974 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301975 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301976 ALOGD("Force a2dp device switch to update new encoder config");
1977 ret = true;
1978 }
1979
Manish Dewangan671a4202017-08-18 17:30:46 +05301980 if (usecase->stream.out->stream_config_changed) {
1981 ALOGD("Force stream_config_changed to update iec61937 transmission config");
1982 return true;
1983 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301984 return ret;
1985}
1986
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301987bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1988{
1989 bool ret=false;
1990 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1991 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1992 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1993 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1994 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1995 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1996 ret = true;
1997
1998 return ret;
1999}
2000
2001bool is_a2dp_device(snd_device_t out_snd_device)
2002{
2003 bool ret=false;
2004 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2005 ret = true;
2006
2007 return ret;
2008}
2009
2010bool is_bt_soc_on(struct audio_device *adev)
2011{
2012 struct mixer_ctl *ctl;
2013 char *mixer_ctl_name = "BT SOC status";
2014 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2015 bool bt_soc_status = true;
2016 if (!ctl) {
2017 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2018 __func__, mixer_ctl_name);
2019 /*This is to ensure we dont break targets which dont have the kernel change*/
2020 return true;
2021 }
2022 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2023 ALOGD("BT SOC status: %d",bt_soc_status);
2024 return bt_soc_status;
2025}
2026
2027int out_standby_l(struct audio_stream *stream);
2028
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002029int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002031 snd_device_t out_snd_device = SND_DEVICE_NONE;
2032 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002033 struct audio_usecase *usecase = NULL;
2034 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002035 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002036 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302037 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002038 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002039 int status = 0;
Jhansi Konathala902fc412018-09-05 13:21:44 +05302040 audio_devices_t audio_device = AUDIO_DEVICE_NONE;
2041 audio_channel_mask_t channel_mask = AUDIO_CHANNEL_NONE;
2042 int sample_rate = 0;
2043 int acdb_id = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302045 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2046
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002047 usecase = get_usecase_from_list(adev, uc_id);
2048 if (usecase == NULL) {
2049 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2050 return -EINVAL;
2051 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002053 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002054 (usecase->type == VOIP_CALL) ||
2055 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302056 if(usecase->stream.out == NULL) {
2057 ALOGE("%s: stream.out is NULL", __func__);
2058 return -EINVAL;
2059 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002060 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002061 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002062 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002063 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302064 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302065 if (usecase->stream.inout == NULL) {
2066 ALOGE("%s: stream.inout is NULL", __func__);
2067 return -EINVAL;
2068 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302069 stream_out.devices = usecase->stream.inout->out_config.devices;
2070 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2071 stream_out.format = usecase->stream.inout->out_config.format;
2072 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2073 out_snd_device = platform_get_output_snd_device(adev->platform,
2074 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302075 usecase->devices = out_snd_device;
2076 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2077 if (usecase->stream.inout == NULL) {
2078 ALOGE("%s: stream.inout is NULL", __func__);
2079 return -EINVAL;
2080 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302081 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302082 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002083 } else {
2084 /*
2085 * If the voice call is active, use the sound devices of voice call usecase
2086 * so that it would not result any device switch. All the usecases will
2087 * be switched to new device when select_devices() is called for voice call
2088 * usecase. This is to avoid switching devices for voice call when
2089 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002090 * choose voice call device only if the use case device is
2091 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002092 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002093 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002094 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002095 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002096 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2097 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302098 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2099 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002100 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002101 in_snd_device = vc_usecase->in_snd_device;
2102 out_snd_device = vc_usecase->out_snd_device;
2103 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002104 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002105 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002106 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002107 if ((voip_usecase != NULL) &&
2108 (usecase->type == PCM_PLAYBACK) &&
2109 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002110 out_snd_device_backend_match = platform_check_backends_match(
2111 voip_usecase->out_snd_device,
2112 platform_get_output_snd_device(
2113 adev->platform,
2114 usecase->stream.out));
2115 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002116 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002117 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2118 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002119 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002120 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002121 in_snd_device = voip_usecase->in_snd_device;
2122 out_snd_device = voip_usecase->out_snd_device;
2123 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002124 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002125 hfp_ucid = audio_extn_hfp_get_usecase();
2126 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002127 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002128 in_snd_device = hfp_usecase->in_snd_device;
2129 out_snd_device = hfp_usecase->out_snd_device;
2130 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002131 }
2132 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302133 if (usecase->stream.out == NULL) {
2134 ALOGE("%s: stream.out is NULL", __func__);
2135 return -EINVAL;
2136 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002137 usecase->devices = usecase->stream.out->devices;
2138 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002139 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002140 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002141 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002142 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizb27e7952018-10-12 15:49:35 +08002143 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002144 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2145
2146 if ((usecase->stream.out != NULL &&
2147 voip_usecase != NULL &&
2148 usecase->stream.out->usecase == voip_usecase->id) &&
2149 adev->active_input &&
kunleizb27e7952018-10-12 15:49:35 +08002150 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002151 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002152 select_devices(adev, adev->active_input->usecase);
2153 }
2154 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002155 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302156 if (usecase->stream.in == NULL) {
2157 ALOGE("%s: stream.in is NULL", __func__);
2158 return -EINVAL;
2159 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002160 usecase->devices = usecase->stream.in->device;
2161 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002162 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002163 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002164 if (adev->active_input &&
2165 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302166 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002167 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2168 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2169 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2170 out_device = voip_usecase->stream.out->devices;
2171 else if (adev->primary_output && !adev->primary_output->standby)
2172 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002173 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002174 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2175 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002176 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002177 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002178 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002179 }
2180 }
2181
2182 if (out_snd_device == usecase->out_snd_device &&
2183 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302184
2185 if (!force_device_switch(usecase))
2186 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002187 }
2188
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302189 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
2190 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
2191 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2192 return 0;
2193 }
2194
sangwoobc677242013-08-08 16:53:43 +09002195 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07002196 out_snd_device, platform_get_snd_device_name(out_snd_device),
2197 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002199 /*
2200 * Limitation: While in call, to do a device switch we need to disable
2201 * and enable both RX and TX devices though one of them is same as current
2202 * device.
2203 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002204 if ((usecase->type == VOICE_CALL) &&
2205 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2206 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002207 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002208 }
2209
2210 if (((usecase->type == VOICE_CALL) ||
2211 (usecase->type == VOIP_CALL)) &&
2212 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2213 /* Disable sidetone only if voice/voip call already exists */
2214 if (voice_is_call_state_active(adev) ||
2215 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002216 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002217
2218 /* Disable aanc only if voice call exists */
2219 if (voice_is_call_state_active(adev))
2220 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002221 }
2222
Zhou Songc66eb7e2017-08-08 18:29:07 +08002223 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302224 (!audio_extn_a2dp_is_ready())) {
2225 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002226 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302227 }
2228
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002229 /* Disable current sound devices */
2230 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002231 disable_audio_route(adev, usecase);
2232 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002233 }
2234
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002235 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002236 disable_audio_route(adev, usecase);
2237 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238 }
2239
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002240 /* Applicable only on the targets that has external modem.
2241 * New device information should be sent to modem before enabling
2242 * the devices to reduce in-call device switch time.
2243 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002244 if ((usecase->type == VOICE_CALL) &&
2245 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2246 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002247 status = platform_switch_voice_call_enable_device_config(adev->platform,
2248 out_snd_device,
2249 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002250 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002251
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002252 /* Enable new sound devices */
2253 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002254 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302255 if (platform_check_codec_asrc_support(adev->platform))
2256 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002257 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258 }
2259
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002260 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302261 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002262 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002263 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002264
Avinash Vaish71a8b972014-07-24 15:36:33 +05302265 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002266 status = platform_switch_voice_call_device_post(adev->platform,
2267 out_snd_device,
2268 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302269 enable_audio_route_for_voice_usecases(adev, usecase);
2270 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002271
sangwoo170731f2013-06-08 15:36:36 +09002272 usecase->in_snd_device = in_snd_device;
2273 usecase->out_snd_device = out_snd_device;
2274
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302275 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2276 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302277 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002278 if ((24 == usecase->stream.out->bit_width) &&
2279 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2280 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2281 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2282 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2283 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2284 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2285 /*
2286 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2287 * configured device sample rate, if not update the COPP rate to be equal to the
2288 * device sample rate, else open COPP at stream sample rate
2289 */
2290 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2291 usecase->stream.out->sample_rate,
2292 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302293 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2294 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002295 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2296 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2297 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2298 }
2299
Weiyin Jiang5d608082018-02-01 17:24:33 +08002300 /* Cache stream information to be notified to gef clients */
2301 audio_device = usecase->stream.out->devices;
2302 channel_mask = usecase->stream.out->channel_mask;
2303 sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
2304 acdb_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302305 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002306 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002307
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002308 /* If input stream is already running then effect needs to be
2309 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002310 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2311 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002312 check_and_enable_effect(adev);
2313
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002314 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002315 /* Enable aanc only if voice call exists */
2316 if (voice_is_call_state_active(adev))
2317 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2318
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002319 /* Enable sidetone only if other voice/voip call already exists */
2320 if (voice_is_call_state_active(adev) ||
2321 voice_extn_compress_voip_is_started(adev))
2322 voice_set_sidetone(adev, out_snd_device, true);
2323 }
2324
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002325 /* Applicable only on the targets that has external modem.
2326 * Enable device command should be sent to modem only after
2327 * enabling voice call mixer controls
2328 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002329 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002330 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2331 out_snd_device,
2332 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302333
2334 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2335
2336 if (usecase->type == VOIP_CALL) {
2337 if (adev->active_input != NULL &&
2338 !adev->active_input->standby) {
2339 if (is_bt_soc_on(adev) == false){
2340 ALOGD("BT SCO MIC disconnected while in connection");
2341 if (adev->active_input->pcm != NULL)
2342 pcm_stop(adev->active_input->pcm);
2343 }
2344 }
2345 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2346 && usecase->stream.out->started) {
2347 if (is_bt_soc_on(adev) == false) {
2348 ALOGD("BT SCO/A2DP disconnected while in connection");
2349 out_standby_l(&usecase->stream.out->stream.common);
2350 }
2351 }
2352 } else if ((usecase->stream.out != NULL) &&
2353 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2354 usecase->stream.out->started) {
2355 if (is_bt_soc_on(adev) == false) {
2356 ALOGD("BT SCO/A2dp disconnected while in connection");
2357 out_standby_l(&usecase->stream.out->stream.common);
2358 }
2359 }
2360 }
2361
Weiyin Jiang5d608082018-02-01 17:24:33 +08002362 /* Notify device change info to effect clients registered
2363 * NOTE: device lock has to be unlock temporarily here.
2364 * To the worst case, we notify stale info to clients.
2365 */
2366 if (usecase->type == PCM_PLAYBACK) {
2367 pthread_mutex_unlock(&adev->lock);
2368 audio_extn_gef_notify_device_config(audio_device, channel_mask, sample_rate, acdb_id);
2369 pthread_mutex_lock(&adev->lock);
2370 }
2371
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302372 ALOGD("%s: done",__func__);
2373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374 return status;
2375}
2376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002377static int stop_input_stream(struct stream_in *in)
2378{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302379 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002380 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302381
2382 if (in == NULL) {
2383 ALOGE("%s: stream_in ptr is NULL", __func__);
2384 return -EINVAL;
2385 }
2386
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002387 struct audio_device *adev = in->dev;
2388
Eric Laurent994a6932013-07-17 11:51:42 -07002389 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002390 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002391 uc_info = get_usecase_from_list(adev, in->usecase);
2392 if (uc_info == NULL) {
2393 ALOGE("%s: Could not find the usecase (%d) in the list",
2394 __func__, in->usecase);
2395 return -EINVAL;
2396 }
2397
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002398 /* Close in-call recording streams */
2399 voice_check_and_stop_incall_rec_usecase(adev, in);
2400
Eric Laurent150dbfe2013-02-27 14:31:02 -08002401 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002402 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002403
2404 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002405 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002406
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002407 list_remove(&uc_info->list);
2408 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002409
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002410 adev->active_input = get_next_active_input(adev);
2411
Eric Laurent994a6932013-07-17 11:51:42 -07002412 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002413 return ret;
2414}
2415
2416int start_input_stream(struct stream_in *in)
2417{
2418 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002419 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002420 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302421
2422 if (in == NULL) {
2423 ALOGE("%s: stream_in ptr is NULL", __func__);
2424 return -EINVAL;
2425 }
2426
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002427 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002428 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002429 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430
Mingming Yin2664a5b2015-09-03 10:53:11 -07002431 if (get_usecase_from_list(adev, usecase) == NULL)
2432 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302433 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2434 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002435
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302436 if (CARD_STATUS_OFFLINE == in->card_status||
2437 CARD_STATUS_OFFLINE == adev->card_status) {
2438 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302439 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302440 goto error_config;
2441 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302442
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302443 if (audio_is_bluetooth_sco_device(in->device)) {
2444 if (!adev->bt_sco_on) {
2445 ALOGE("%s: SCO profile is not ready, return error", __func__);
2446 ret = -EIO;
2447 goto error_config;
2448 }
2449 }
2450
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002451 /* Check if source matches incall recording usecase criteria */
2452 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2453 if (ret)
2454 goto error_config;
2455 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002456 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2457
2458 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2459 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2460 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002461 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002462 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002463
Eric Laurentb23d5282013-05-14 15:27:20 -07002464 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465 if (in->pcm_device_id < 0) {
2466 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2467 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002468 ret = -EINVAL;
2469 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002471
2472 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002473 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002474
2475 if (!uc_info) {
2476 ret = -ENOMEM;
2477 goto error_config;
2478 }
2479
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480 uc_info->id = in->usecase;
2481 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002482 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002483 uc_info->devices = in->device;
2484 uc_info->in_snd_device = SND_DEVICE_NONE;
2485 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002487 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302488 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2489 adev->perf_lock_opts,
2490 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002491 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492
Haynes Mathew George16081042017-05-31 17:16:49 -07002493 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302494 ret = audio_extn_cin_start_input_stream(in);
2495 if (ret)
2496 goto error_open;
2497 else
2498 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002499 }
2500
Haynes Mathew George16081042017-05-31 17:16:49 -07002501 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002502 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002503 ALOGE("%s: pcm stream not ready", __func__);
2504 goto error_open;
2505 }
2506 ret = pcm_start(in->pcm);
2507 if (ret < 0) {
2508 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2509 goto error_open;
2510 }
2511 } else {
2512 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2513 unsigned int pcm_open_retry_count = 0;
2514
2515 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2516 flags |= PCM_MMAP | PCM_NOIRQ;
2517 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2518 } else if (in->realtime) {
2519 flags |= PCM_MMAP | PCM_NOIRQ;
2520 }
2521
Garmond Leunge2433c32017-09-28 21:51:22 -07002522 if (audio_extn_ffv_get_stream() == in) {
2523 ALOGD("%s: ffv stream, update pcm config", __func__);
2524 audio_extn_ffv_update_pcm_config(&config);
2525 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002526 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2527 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2528
2529 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002530 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002531 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002532 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002533 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302534 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302535 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2536 adev->card_status = CARD_STATUS_OFFLINE;
2537 in->card_status = CARD_STATUS_OFFLINE;
2538 ret = -EIO;
2539 goto error_open;
2540 }
2541
Haynes Mathew George16081042017-05-31 17:16:49 -07002542 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2543 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2544 if (in->pcm != NULL) {
2545 pcm_close(in->pcm);
2546 in->pcm = NULL;
2547 }
2548 if (pcm_open_retry_count-- == 0) {
2549 ret = -EIO;
2550 goto error_open;
2551 }
2552 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2553 continue;
2554 }
2555 break;
2556 }
2557
2558 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002559 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002560 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002561 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002562 if (ret < 0) {
2563 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2564 pcm_close(in->pcm);
2565 in->pcm = NULL;
2566 goto error_open;
2567 }
2568 register_in_stream(in);
2569 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002570 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002571 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002572 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002573 if (ret < 0) {
2574 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002575 pcm_close(in->pcm);
2576 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002577 goto error_open;
2578 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002579 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002580 }
2581
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002582 check_and_enable_effect(adev);
2583
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302584done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302585 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002586 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002587
Eric Laurentc8400632013-02-14 19:04:54 -08002588 return ret;
2589
2590error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302591 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002593error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302594 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302595 /*
2596 * sleep 50ms to allow sufficient time for kernel
2597 * drivers to recover incases like SSR.
2598 */
2599 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002600 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002601
2602 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603}
2604
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002605void lock_input_stream(struct stream_in *in)
2606{
2607 pthread_mutex_lock(&in->pre_lock);
2608 pthread_mutex_lock(&in->lock);
2609 pthread_mutex_unlock(&in->pre_lock);
2610}
2611
2612void lock_output_stream(struct stream_out *out)
2613{
2614 pthread_mutex_lock(&out->pre_lock);
2615 pthread_mutex_lock(&out->lock);
2616 pthread_mutex_unlock(&out->pre_lock);
2617}
2618
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002619/* must be called with out->lock locked */
2620static int send_offload_cmd_l(struct stream_out* out, int command)
2621{
2622 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2623
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002624 if (!cmd) {
2625 ALOGE("failed to allocate mem for command 0x%x", command);
2626 return -ENOMEM;
2627 }
2628
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002629 ALOGVV("%s %d", __func__, command);
2630
2631 cmd->cmd = command;
2632 list_add_tail(&out->offload_cmd_list, &cmd->node);
2633 pthread_cond_signal(&out->offload_cond);
2634 return 0;
2635}
2636
2637/* must be called iwth out->lock locked */
2638static void stop_compressed_output_l(struct stream_out *out)
2639{
2640 out->offload_state = OFFLOAD_STATE_IDLE;
2641 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002642 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002643 if (out->compr != NULL) {
2644 compress_stop(out->compr);
2645 while (out->offload_thread_blocked) {
2646 pthread_cond_wait(&out->cond, &out->lock);
2647 }
2648 }
2649}
2650
Varun Balaraje49253e2017-07-06 19:48:56 +05302651bool is_interactive_usecase(audio_usecase_t uc_id)
2652{
2653 unsigned int i;
2654 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2655 if (uc_id == interactive_usecases[i])
2656 return true;
2657 }
2658 return false;
2659}
2660
2661static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2662{
2663 audio_usecase_t ret_uc = USECASE_INVALID;
2664 unsigned int intract_uc_index;
2665 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2666
2667 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2668 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2669 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2670 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2671 ret_uc = interactive_usecases[intract_uc_index];
2672 break;
2673 }
2674 }
2675
2676 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2677 return ret_uc;
2678}
2679
2680static void free_interactive_usecase(struct audio_device *adev,
2681 audio_usecase_t uc_id)
2682{
2683 unsigned int interact_uc_index;
2684 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2685
2686 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2687 if (interactive_usecases[interact_uc_index] == uc_id) {
2688 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2689 break;
2690 }
2691 }
2692 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2693}
2694
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002695bool is_offload_usecase(audio_usecase_t uc_id)
2696{
2697 unsigned int i;
2698 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2699 if (uc_id == offload_usecases[i])
2700 return true;
2701 }
2702 return false;
2703}
2704
Dhananjay Kumarac341582017-02-23 23:42:25 +05302705static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002706{
vivek mehta446c3962015-09-14 10:57:35 -07002707 audio_usecase_t ret_uc = USECASE_INVALID;
2708 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002709 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002710 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302711 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002712 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2713 else
2714 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002715
vivek mehta446c3962015-09-14 10:57:35 -07002716 pthread_mutex_lock(&adev->lock);
2717 if (get_usecase_from_list(adev, ret_uc) != NULL)
2718 ret_uc = USECASE_INVALID;
2719 pthread_mutex_unlock(&adev->lock);
2720
2721 return ret_uc;
2722 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002723
2724 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002725 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2726 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2727 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2728 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002729 break;
2730 }
2731 }
vivek mehta446c3962015-09-14 10:57:35 -07002732
2733 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2734 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002735}
2736
2737static void free_offload_usecase(struct audio_device *adev,
2738 audio_usecase_t uc_id)
2739{
vivek mehta446c3962015-09-14 10:57:35 -07002740 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002741 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002742
2743 if (!adev->multi_offload_enable)
2744 return;
2745
2746 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2747 if (offload_usecases[offload_uc_index] == uc_id) {
2748 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002749 break;
2750 }
2751 }
2752 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2753}
2754
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002755static void *offload_thread_loop(void *context)
2756{
2757 struct stream_out *out = (struct stream_out *) context;
2758 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002759 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002760
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002761 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2762 set_sched_policy(0, SP_FOREGROUND);
2763 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2764
2765 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002766 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002767 for (;;) {
2768 struct offload_cmd *cmd = NULL;
2769 stream_callback_event_t event;
2770 bool send_callback = false;
2771
2772 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2773 __func__, list_empty(&out->offload_cmd_list),
2774 out->offload_state);
2775 if (list_empty(&out->offload_cmd_list)) {
2776 ALOGV("%s SLEEPING", __func__);
2777 pthread_cond_wait(&out->offload_cond, &out->lock);
2778 ALOGV("%s RUNNING", __func__);
2779 continue;
2780 }
2781
2782 item = list_head(&out->offload_cmd_list);
2783 cmd = node_to_item(item, struct offload_cmd, node);
2784 list_remove(item);
2785
2786 ALOGVV("%s STATE %d CMD %d out->compr %p",
2787 __func__, out->offload_state, cmd->cmd, out->compr);
2788
2789 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2790 free(cmd);
2791 break;
2792 }
2793
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002794 // allow OFFLOAD_CMD_ERROR reporting during standby
2795 // this is needed to handle failures during compress_open
2796 // Note however that on a pause timeout, the stream is closed
2797 // and no offload usecase will be active. Therefore this
2798 // special case is needed for compress_open failures alone
2799 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2800 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002801 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002802 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002803 pthread_cond_signal(&out->cond);
2804 continue;
2805 }
2806 out->offload_thread_blocked = true;
2807 pthread_mutex_unlock(&out->lock);
2808 send_callback = false;
2809 switch(cmd->cmd) {
2810 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002811 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002812 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002813 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002814 send_callback = true;
2815 event = STREAM_CBK_EVENT_WRITE_READY;
2816 break;
2817 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002818 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302819 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002820 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302821 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002822 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302823 if (ret < 0)
2824 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302825 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302826 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002827 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002828 else
2829 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002830 if (-ENETRESET != ret && !(-EINTR == ret &&
2831 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302832 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302833 pthread_mutex_lock(&out->lock);
2834 out->send_new_metadata = 1;
2835 out->send_next_track_params = true;
2836 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302837 event = STREAM_CBK_EVENT_DRAIN_READY;
2838 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2839 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302840 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002841 break;
2842 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002843 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002844 ret = compress_drain(out->compr);
2845 ALOGD("copl(%p):out of compress_drain", out);
2846 // EINTR check avoids drain interruption due to SSR
2847 if (-ENETRESET != ret && !(-EINTR == ret &&
2848 CARD_STATUS_OFFLINE == out->card_status)) {
2849 send_callback = true;
2850 event = STREAM_CBK_EVENT_DRAIN_READY;
2851 } else
2852 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002853 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302854 case OFFLOAD_CMD_ERROR:
2855 ALOGD("copl(%p): sending error callback to AF", out);
2856 send_callback = true;
2857 event = STREAM_CBK_EVENT_ERROR;
2858 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002859 default:
2860 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2861 break;
2862 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002863 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002864 out->offload_thread_blocked = false;
2865 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002866 if (send_callback && out->client_callback) {
2867 ALOGVV("%s: sending client_callback event %d", __func__, event);
2868 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002869 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002870 free(cmd);
2871 }
2872
2873 pthread_cond_signal(&out->cond);
2874 while (!list_empty(&out->offload_cmd_list)) {
2875 item = list_head(&out->offload_cmd_list);
2876 list_remove(item);
2877 free(node_to_item(item, struct offload_cmd, node));
2878 }
2879 pthread_mutex_unlock(&out->lock);
2880
2881 return NULL;
2882}
2883
2884static int create_offload_callback_thread(struct stream_out *out)
2885{
2886 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2887 list_init(&out->offload_cmd_list);
2888 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2889 offload_thread_loop, out);
2890 return 0;
2891}
2892
2893static int destroy_offload_callback_thread(struct stream_out *out)
2894{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002895 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896 stop_compressed_output_l(out);
2897 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2898
2899 pthread_mutex_unlock(&out->lock);
2900 pthread_join(out->offload_thread, (void **) NULL);
2901 pthread_cond_destroy(&out->offload_cond);
2902
2903 return 0;
2904}
2905
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002906static int stop_output_stream(struct stream_out *out)
2907{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302908 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002909 struct audio_usecase *uc_info;
2910 struct audio_device *adev = out->dev;
2911
Eric Laurent994a6932013-07-17 11:51:42 -07002912 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002913 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002914 uc_info = get_usecase_from_list(adev, out->usecase);
2915 if (uc_info == NULL) {
2916 ALOGE("%s: Could not find the usecase (%d) in the list",
2917 __func__, out->usecase);
2918 return -EINVAL;
2919 }
2920
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002921 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302922 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002923 if (adev->visualizer_stop_output != NULL)
2924 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002925
2926 audio_extn_dts_remove_state_notifier_node(out->usecase);
2927
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002928 if (adev->offload_effects_stop_output != NULL)
2929 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2930 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002931
Arun Mirpurief53ce52018-09-11 18:00:09 -07002932 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2933 voice_set_device_mute_flag(adev, false);
2934
Eric Laurent150dbfe2013-02-27 14:31:02 -08002935 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002936 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002937
2938 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002939 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002940
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002941 if (is_offload_usecase(out->usecase)) {
2942 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2943 adev->dsp_bit_width_enforce_mode,
2944 false);
2945 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07002946 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2947 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
2948 false);
2949
2950 if (ret != 0)
2951 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
2952 /* default service interval was successfully updated,
2953 reopen USB backend with new service interval */
2954 ret = 0;
2955 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002956
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002957 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302958 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002959 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302960 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002961 ALOGV("Disable passthrough , reset mixer to pcm");
2962 /* NO_PASSTHROUGH */
2963 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002964 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002965 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2966 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002967
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302968 /* Must be called after removing the usecase from list */
2969 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05302970 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302971
Manish Dewangan21a850a2017-08-14 12:03:55 +05302972 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002973 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2974 if (ret < 0)
2975 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2976 }
2977
Garmond Leung5fd0b552018-04-17 11:56:12 -07002978 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002979 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980 return ret;
2981}
2982
2983int start_output_stream(struct stream_out *out)
2984{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986 struct audio_usecase *uc_info;
2987 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002988 char mixer_ctl_name[128];
2989 struct mixer_ctl *ctl = NULL;
2990 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302991 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992
Haynes Mathew George380745d2017-10-04 15:27:45 -07002993 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002994 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2995 ret = -EINVAL;
2996 goto error_config;
2997 }
2998
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302999 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
3000 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
3001 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303002
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303003 if (CARD_STATUS_OFFLINE == out->card_status ||
3004 CARD_STATUS_OFFLINE == adev->card_status) {
3005 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303006 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303007 goto error_config;
3008 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303009
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303010 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
3011 if (!audio_extn_a2dp_is_ready()) {
3012 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303013 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303014 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303015 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3016 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3017 ret = -EAGAIN;
3018 goto error_config;
3019 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303020 }
3021 }
3022 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303023 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3024 if (!adev->bt_sco_on) {
3025 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3026 //combo usecase just by pass a2dp
3027 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3028 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3029 } else {
3030 ALOGE("%s: SCO profile is not ready, return error", __func__);
3031 ret = -EAGAIN;
3032 goto error_config;
3033 }
3034 }
3035 }
3036
Eric Laurentb23d5282013-05-14 15:27:20 -07003037 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038 if (out->pcm_device_id < 0) {
3039 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3040 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003041 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003042 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043 }
3044
3045 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003046
3047 if (!uc_info) {
3048 ret = -ENOMEM;
3049 goto error_config;
3050 }
3051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052 uc_info->id = out->usecase;
3053 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003054 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003055 uc_info->devices = out->devices;
3056 uc_info->in_snd_device = SND_DEVICE_NONE;
3057 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003058
3059 /* This must be called before adding this usecase to the list */
3060 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3061 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3062 /* USB backend is not reopened immediately.
3063 This is eventually done as part of select_devices */
3064 }
3065
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003066 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303068 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3069 adev->perf_lock_opts,
3070 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303071
3072 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303073 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303074 if (audio_extn_passthru_is_enabled() &&
3075 audio_extn_passthru_is_passthrough_stream(out)) {
3076 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303077 }
3078 }
3079
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303080 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3081 (!audio_extn_a2dp_is_ready())) {
3082 if (!a2dp_combo) {
3083 check_a2dp_restore_l(adev, out, false);
3084 } else {
3085 audio_devices_t dev = out->devices;
3086 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3087 select_devices(adev, out->usecase);
3088 out->devices = dev;
3089 }
3090 } else {
3091 select_devices(adev, out->usecase);
3092 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003093
Arun Mirpurief53ce52018-09-11 18:00:09 -07003094 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3095 voice_set_device_mute_flag(adev, true);
3096
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003097 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3098 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003099
3100 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3101 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3102 ALOGE("%s: pcm stream not ready", __func__);
3103 goto error_open;
3104 }
3105 ret = pcm_start(out->pcm);
3106 if (ret < 0) {
3107 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3108 goto error_open;
3109 }
3110 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003111 unsigned int flags = PCM_OUT;
3112 unsigned int pcm_open_retry_count = 0;
3113 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3114 flags |= PCM_MMAP | PCM_NOIRQ;
3115 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003116 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003117 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003118 } else
3119 flags |= PCM_MONOTONIC;
3120
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003121 if ((adev->vr_audio_mode_enabled) &&
3122 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3123 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3124 "PCM_Dev %d Topology", out->pcm_device_id);
3125 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3126 if (!ctl) {
3127 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3128 __func__, mixer_ctl_name);
3129 } else {
3130 //if success use ULLPP
3131 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3132 __func__, mixer_ctl_name, out->pcm_device_id);
3133 //There is a still a possibility that some sessions
3134 // that request for FAST|RAW when 3D audio is active
3135 //can go through ULLPP. Ideally we expects apps to
3136 //listen to audio focus and stop concurrent playback
3137 //Also, we will look for mode flag (voice_in_communication)
3138 //before enabling the realtime flag.
3139 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3140 }
3141 }
3142
Surendar Karka91fa3682018-07-02 18:12:12 +05303143 if (out->realtime)
3144 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3145 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3146
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003147 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003148 ATRACE_BEGIN("pcm_open");
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003149 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3150 flags, &out->config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003151 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303152 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303153 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3154 out->card_status = CARD_STATUS_OFFLINE;
3155 adev->card_status = CARD_STATUS_OFFLINE;
3156 ret = -EIO;
3157 goto error_open;
3158 }
3159
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003160 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3161 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3162 if (out->pcm != NULL) {
3163 pcm_close(out->pcm);
3164 out->pcm = NULL;
3165 }
3166 if (pcm_open_retry_count-- == 0) {
3167 ret = -EIO;
3168 goto error_open;
3169 }
3170 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3171 continue;
3172 }
3173 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003174 }
Surendar Karka91fa3682018-07-02 18:12:12 +05303175 if (!out->realtime)
3176 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303177 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003178
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003179 ALOGV("%s: pcm_prepare", __func__);
3180 if (pcm_is_ready(out->pcm)) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003181 ATRACE_BEGIN("pcm_prepare");
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003182 ret = pcm_prepare(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003183 ATRACE_END();
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003184 if (ret < 0) {
3185 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3186 pcm_close(out->pcm);
3187 out->pcm = NULL;
3188 goto error_open;
3189 }
3190 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08003191 // apply volume for voip playback after path is set up
3192 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3193 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303194 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) &&
3195 (out->apply_volume)) {
3196 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3197 out->apply_volume = false;
3198 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003199 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003200 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303201 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003202 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3203 adev->dsp_bit_width_enforce_mode,
3204 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003205 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003206 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003207 out->compr = compress_open(adev->snd_card,
3208 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003209 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003210 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303211 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303212 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3213 adev->card_status = CARD_STATUS_OFFLINE;
3214 out->card_status = CARD_STATUS_OFFLINE;
3215 ret = -EIO;
3216 goto error_open;
3217 }
3218
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003219 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003220 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003221 compress_close(out->compr);
3222 out->compr = NULL;
3223 ret = -EIO;
3224 goto error_open;
3225 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303226 /* compress_open sends params of the track, so reset the flag here */
3227 out->is_compr_metadata_avail = false;
3228
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003229 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003230 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003231
Fred Oh3f43e742015-03-04 18:42:34 -08003232 /* Since small bufs uses blocking writes, a write will be blocked
3233 for the default max poll time (20s) in the event of an SSR.
3234 Reduce the poll time to observe and deal with SSR faster.
3235 */
Ashish Jain5106d362016-05-11 19:23:33 +05303236 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003237 compress_set_max_poll_wait(out->compr, 1000);
3238 }
3239
Manish Dewangan69426c82017-01-30 17:35:36 +05303240 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303241 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303242
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003243 audio_extn_dts_create_state_notifier_node(out->usecase);
3244 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3245 popcount(out->channel_mask),
3246 out->playback_started);
3247
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003248#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303249 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003250 audio_extn_dolby_send_ddp_endp_params(adev);
3251#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303252 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3253 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003254 if (adev->visualizer_start_output != NULL)
3255 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3256 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303257 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003258 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003259 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003261
3262 if (ret == 0) {
3263 register_out_stream(out);
3264 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003265 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3266 ALOGE("%s: pcm stream not ready", __func__);
3267 goto error_open;
3268 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003269 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003270 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003271 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003272 if (ret < 0)
3273 goto error_open;
3274 }
3275 }
3276
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303277 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003278 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003279
Manish Dewangan21a850a2017-08-14 12:03:55 +05303280 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003281 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003282 if (ret < 0)
3283 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3284 }
3285
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003286 // consider a scenario where on pause lower layers are tear down.
3287 // so on resume, swap mixer control need to be sent only when
3288 // backend is active, hence rather than sending from enable device
3289 // sending it from start of streamtream
3290
3291 platform_set_swap_channels(adev, true);
3292
Haynes Mathew George380745d2017-10-04 15:27:45 -07003293 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003294 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003295error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303296 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003297 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003298error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303299 /*
3300 * sleep 50ms to allow sufficient time for kernel
3301 * drivers to recover incases like SSR.
3302 */
3303 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003304 ATRACE_END();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003305 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306}
3307
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003308static int check_input_parameters(uint32_t sample_rate,
3309 audio_format_t format,
3310 int channel_count)
3311{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003312 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303314 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3315 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3316 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003317 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003318 !audio_extn_compr_cap_format_supported(format) &&
3319 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003320 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003321
3322 switch (channel_count) {
3323 case 1:
3324 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303325 case 3:
3326 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003327 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003328 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003329 break;
3330 default:
3331 ret = -EINVAL;
3332 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333
3334 switch (sample_rate) {
3335 case 8000:
3336 case 11025:
3337 case 12000:
3338 case 16000:
3339 case 22050:
3340 case 24000:
3341 case 32000:
3342 case 44100:
3343 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003344 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303345 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003346 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303347 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348 break;
3349 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003350 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351 }
3352
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003353 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354}
3355
Naresh Tanniru04f71882018-06-26 17:46:22 +05303356
3357/** Add a value in a list if not already present.
3358 * @return true if value was successfully inserted or already present,
3359 * false if the list is full and does not contain the value.
3360 */
3361static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3362 for (size_t i = 0; i < list_length; i++) {
3363 if (list[i] == value) return true; // value is already present
3364 if (list[i] == 0) { // no values in this slot
3365 list[i] = value;
3366 return true; // value inserted
3367 }
3368 }
3369 return false; // could not insert value
3370}
3371
3372/** Add channel_mask in supported_channel_masks if not already present.
3373 * @return true if channel_mask was successfully inserted or already present,
3374 * false if supported_channel_masks is full and does not contain channel_mask.
3375 */
3376static void register_channel_mask(audio_channel_mask_t channel_mask,
3377 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3378 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3379 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3380}
3381
3382/** Add format in supported_formats if not already present.
3383 * @return true if format was successfully inserted or already present,
3384 * false if supported_formats is full and does not contain format.
3385 */
3386static void register_format(audio_format_t format,
3387 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3388 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3389 "%s: stream can not declare supporting its format %x", __func__, format);
3390}
3391/** Add sample_rate in supported_sample_rates if not already present.
3392 * @return true if sample_rate was successfully inserted or already present,
3393 * false if supported_sample_rates is full and does not contain sample_rate.
3394 */
3395static void register_sample_rate(uint32_t sample_rate,
3396 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3397 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3398 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3399}
3400
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401static size_t get_input_buffer_size(uint32_t sample_rate,
3402 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003403 int channel_count,
3404 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405{
3406 size_t size = 0;
3407
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003408 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3409 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003410
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003411 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003412 if (is_low_latency)
3413 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303414
3415 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003417 /* make sure the size is multiple of 32 bytes
3418 * At 48 kHz mono 16-bit PCM:
3419 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3420 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
3421 */
3422 size += 0x1f;
3423 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003424
3425 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426}
3427
Ashish Jain058165c2016-09-28 23:18:48 +05303428static size_t get_output_period_size(uint32_t sample_rate,
3429 audio_format_t format,
3430 int channel_count,
3431 int duration /*in millisecs*/)
3432{
3433 size_t size = 0;
3434 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3435
3436 if ((duration == 0) || (sample_rate == 0) ||
3437 (bytes_per_sample == 0) || (channel_count == 0)) {
3438 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3439 bytes_per_sample, channel_count);
3440 return -EINVAL;
3441 }
3442
3443 size = (sample_rate *
3444 duration *
3445 bytes_per_sample *
3446 channel_count) / 1000;
3447 /*
3448 * To have same PCM samples for all channels, the buffer size requires to
3449 * be multiple of (number of channels * bytes per sample)
3450 * For writes to succeed, the buffer must be written at address which is multiple of 32
3451 */
3452 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3453
3454 return (size/(channel_count * bytes_per_sample));
3455}
3456
Zhou Song48453a02018-01-10 17:50:59 +08003457static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303458{
3459 uint64_t actual_frames_rendered = 0;
3460 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3461
3462 /* This adjustment accounts for buffering after app processor.
3463 * It is based on estimated DSP latency per use case, rather than exact.
3464 */
3465 int64_t platform_latency = platform_render_latency(out->usecase) *
3466 out->sample_rate / 1000000LL;
3467
Zhou Song48453a02018-01-10 17:50:59 +08003468 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303469 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3470 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3471 * hence only estimate.
3472 */
3473 int64_t signed_frames = out->written - kernel_buffer_size;
3474
3475 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3476
Zhou Song48453a02018-01-10 17:50:59 +08003477 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303478 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003479 if (timestamp != NULL )
3480 *timestamp = out->writeAt;
3481 } else if (timestamp != NULL) {
3482 clock_gettime(CLOCK_MONOTONIC, timestamp);
3483 }
3484 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303485
3486 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3487 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3488 (long long int)out->written, (int)kernel_buffer_size,
3489 audio_bytes_per_sample(out->compr_config.codec->format),
3490 popcount(out->channel_mask));
3491
3492 return actual_frames_rendered;
3493}
3494
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3496{
3497 struct stream_out *out = (struct stream_out *)stream;
3498
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003499 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003500}
3501
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003502static int out_set_sample_rate(struct audio_stream *stream __unused,
3503 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504{
3505 return -ENOSYS;
3506}
3507
3508static size_t out_get_buffer_size(const struct audio_stream *stream)
3509{
3510 struct stream_out *out = (struct stream_out *)stream;
3511
Varun Balaraje49253e2017-07-06 19:48:56 +05303512 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303513 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303514 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303515 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3516 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3517 else
3518 return out->compr_config.fragment_size;
3519 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003520 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003521 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3522 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 +05303523 else if (is_offload_usecase(out->usecase) &&
3524 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303525 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003526
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003527 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003528 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529}
3530
3531static uint32_t out_get_channels(const struct audio_stream *stream)
3532{
3533 struct stream_out *out = (struct stream_out *)stream;
3534
3535 return out->channel_mask;
3536}
3537
3538static audio_format_t out_get_format(const struct audio_stream *stream)
3539{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003540 struct stream_out *out = (struct stream_out *)stream;
3541
3542 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003543}
3544
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003545static int out_set_format(struct audio_stream *stream __unused,
3546 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547{
3548 return -ENOSYS;
3549}
3550
3551static int out_standby(struct audio_stream *stream)
3552{
3553 struct stream_out *out = (struct stream_out *)stream;
3554 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003555 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003556
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303557 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3558 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003560 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003562 if (adev->adm_deregister_stream)
3563 adev->adm_deregister_stream(adev->adm_data, out->handle);
3564
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003565 if (is_offload_usecase(out->usecase))
3566 stop_compressed_output_l(out);
3567
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003568 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003570 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3571 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303572 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003573 pthread_mutex_unlock(&adev->lock);
3574 pthread_mutex_unlock(&out->lock);
3575 ALOGD("VOIP output entered standby");
3576 return 0;
3577 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003578 if (out->pcm) {
3579 pcm_close(out->pcm);
3580 out->pcm = NULL;
3581 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003582 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3583 do_stop = out->playback_started;
3584 out->playback_started = false;
3585 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003586 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003587 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303588 out->send_next_track_params = false;
3589 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003590 out->gapless_mdata.encoder_delay = 0;
3591 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003592 if (out->compr != NULL) {
3593 compress_close(out->compr);
3594 out->compr = NULL;
3595 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003596 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003597 if (do_stop) {
3598 stop_output_stream(out);
3599 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003600 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003601 }
3602 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303603 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003604 return 0;
3605}
3606
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303607static int out_on_error(struct audio_stream *stream)
3608{
3609 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003610 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303611
3612 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003613 // always send CMD_ERROR for offload streams, this
3614 // is needed e.g. when SSR happens within compress_open
3615 // since the stream is active, offload_callback_thread is also active.
3616 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3617 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003618 }
3619 pthread_mutex_unlock(&out->lock);
3620
3621 status = out_standby(&out->stream.common);
3622
3623 lock_output_stream(out);
3624 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003625 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303626 }
3627 pthread_mutex_unlock(&out->lock);
3628
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003629 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303630}
3631
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303632/*
3633 *standby implementation without locks, assumes that the callee already
3634 *has taken adev and out lock.
3635 */
3636int out_standby_l(struct audio_stream *stream)
3637{
3638 struct stream_out *out = (struct stream_out *)stream;
3639 struct audio_device *adev = out->dev;
3640
3641 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3642 stream, out->usecase, use_case_table[out->usecase]);
3643
3644 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003645 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303646 if (adev->adm_deregister_stream)
3647 adev->adm_deregister_stream(adev->adm_data, out->handle);
3648
3649 if (is_offload_usecase(out->usecase))
3650 stop_compressed_output_l(out);
3651
3652 out->standby = true;
3653 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3654 voice_extn_compress_voip_close_output_stream(stream);
3655 out->started = 0;
3656 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003657 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303658 return 0;
3659 } else if (!is_offload_usecase(out->usecase)) {
3660 if (out->pcm) {
3661 pcm_close(out->pcm);
3662 out->pcm = NULL;
3663 }
3664 } else {
3665 ALOGD("copl(%p):standby", out);
3666 out->send_next_track_params = false;
3667 out->is_compr_metadata_avail = false;
3668 out->gapless_mdata.encoder_delay = 0;
3669 out->gapless_mdata.encoder_padding = 0;
3670 if (out->compr != NULL) {
3671 compress_close(out->compr);
3672 out->compr = NULL;
3673 }
3674 }
3675 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003676 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303677 }
3678 ALOGD("%s: exit", __func__);
3679 return 0;
3680}
3681
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003682static int out_dump(const struct audio_stream *stream __unused,
3683 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684{
3685 return 0;
3686}
3687
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003688static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3689{
3690 int ret = 0;
3691 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003692
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003693 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003694 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003695 return -EINVAL;
3696 }
3697
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303698 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003699
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003700 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3701 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303702 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003703 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003704 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3705 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303706 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003707 }
3708
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003709 ALOGV("%s new encoder delay %u and padding %u", __func__,
3710 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3711
3712 return 0;
3713}
3714
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003715static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3716{
3717 return out == adev->primary_output || out == adev->voice_tx_output;
3718}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003719
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303720// note: this call is safe only if the stream_cb is
3721// removed first in close_output_stream (as is done now).
3722static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3723{
3724 if (!stream || !parms)
3725 return;
3726
3727 struct stream_out *out = (struct stream_out *)stream;
3728 struct audio_device *adev = out->dev;
3729
3730 card_status_t status;
3731 int card;
3732 if (parse_snd_card_status(parms, &card, &status) < 0)
3733 return;
3734
3735 pthread_mutex_lock(&adev->lock);
3736 bool valid_cb = (card == adev->snd_card);
3737 pthread_mutex_unlock(&adev->lock);
3738
3739 if (!valid_cb)
3740 return;
3741
3742 lock_output_stream(out);
3743 if (out->card_status != status)
3744 out->card_status = status;
3745 pthread_mutex_unlock(&out->lock);
3746
3747 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3748 use_case_table[out->usecase],
3749 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3750
3751 if (status == CARD_STATUS_OFFLINE)
3752 out_on_error(stream);
3753
3754 return;
3755}
3756
Kevin Rocardfce19002017-08-07 19:21:36 -07003757static int get_alive_usb_card(struct str_parms* parms) {
3758 int card;
3759 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
3760 !audio_extn_usb_alive(card)) {
3761 return card;
3762 }
3763 return -ENODEV;
3764}
3765
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3767{
3768 struct stream_out *out = (struct stream_out *)stream;
3769 struct audio_device *adev = out->dev;
3770 struct str_parms *parms;
3771 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003772 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303773 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003774 bool reconfig = false;
3775 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776
sangwoobc677242013-08-08 16:53:43 +09003777 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003778 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303780 if (!parms)
3781 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003782 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3783 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003785 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003786 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003788 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003789 * When HDMI cable is unplugged the music playback is paused and
3790 * the policy manager sends routing=0. But the audioflinger continues
3791 * to write data until standby time (3sec). As the HDMI core is
3792 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003793 * Avoid this by routing audio to speaker until standby.
3794 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003795 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3796 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303797 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003798 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3799 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003800 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303801 /*
3802 * When A2DP is disconnected the
3803 * music playback is paused and the policy manager sends routing=0
3804 * But the audioflingercontinues to write data until standby time
3805 * (3sec). As BT is turned off, the write gets blocked.
3806 * Avoid this by routing audio to speaker until standby.
3807 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003808 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07003809 (val == AUDIO_DEVICE_NONE) &&
3810 !audio_extn_a2dp_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303811 val = AUDIO_DEVICE_OUT_SPEAKER;
3812 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05303813 /*
3814 * When USB headset is disconnected the music platback paused
3815 * and the policy manager send routing=0. But if the USB is connected
3816 * back before the standby time, AFE is not closed and opened
3817 * when USB is connected back. So routing to speker will guarantee
3818 * AFE reconfiguration and AFE will be opend once USB is connected again
3819 */
3820 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
3821 (val == AUDIO_DEVICE_NONE) &&
3822 !audio_extn_usb_connected(parms)) {
3823 val = AUDIO_DEVICE_OUT_SPEAKER;
3824 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303825 /* To avoid a2dp to sco overlapping / BT device improper state
3826 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303827 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303828 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3829 if (!audio_extn_a2dp_is_ready()) {
3830 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3831 //combo usecase just by pass a2dp
3832 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303833 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303834 } else {
3835 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3836 /* update device to a2dp and don't route as BT returned error
3837 * However it is still possible a2dp routing called because
3838 * of current active device disconnection (like wired headset)
3839 */
3840 out->devices = val;
3841 pthread_mutex_unlock(&out->lock);
3842 pthread_mutex_unlock(&adev->lock);
3843 goto error;
3844 }
3845 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303846 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003847
3848 audio_devices_t new_dev = val;
3849
3850 // Workaround: If routing to an non existing usb device, fail gracefully
3851 // The routing request will otherwise block during 10 second
3852 int card;
3853 if (audio_is_usb_out_device(new_dev) &&
3854 (card = get_alive_usb_card(parms)) >= 0) {
3855
3856 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
3857 pthread_mutex_unlock(&adev->lock);
3858 pthread_mutex_unlock(&out->lock);
3859 ret = -ENOSYS;
3860 goto routing_fail;
3861 }
3862
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003863 /*
3864 * select_devices() call below switches all the usecases on the same
3865 * backend to the new device. Refer to check_usecases_codec_backend() in
3866 * the select_devices(). But how do we undo this?
3867 *
3868 * For example, music playback is active on headset (deep-buffer usecase)
3869 * and if we go to ringtones and select a ringtone, low-latency usecase
3870 * will be started on headset+speaker. As we can't enable headset+speaker
3871 * and headset devices at the same time, select_devices() switches the music
3872 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3873 * So when the ringtone playback is completed, how do we undo the same?
3874 *
3875 * We are relying on the out_set_parameters() call on deep-buffer output,
3876 * once the ringtone playback is ended.
3877 * NOTE: We should not check if the current devices are same as new devices.
3878 * Because select_devices() must be called to switch back the music
3879 * playback to headset.
3880 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003881 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003882 audio_devices_t new_dev = val;
3883 bool same_dev = out->devices == new_dev;
3884 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003885
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003886 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08003887 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003888 if (adev->mode == AUDIO_MODE_IN_CALL) {
3889 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003890 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3891 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
3892 audio_extn_usb_set_service_interval(true /*playback*/,
3893 service_interval,
3894 &reconfig);
3895 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
3896 }
3897 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003898 }
3899 } else {
3900 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003901 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003902 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003903 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003904
3905 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003906 if (!same_dev) {
3907 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303908 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3909 adev->perf_lock_opts,
3910 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003911 if (adev->adm_on_routing_change)
3912 adev->adm_on_routing_change(adev->adm_data,
3913 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003914 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303915 if (!bypass_a2dp) {
3916 select_devices(adev, out->usecase);
3917 } else {
3918 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3919 select_devices(adev, out->usecase);
3920 out->devices = new_dev;
3921 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003922
3923 if (!same_dev) {
3924 // on device switch force swap, lower functions will make sure
3925 // to check if swap is allowed or not.
3926 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05303927 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003928 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303929 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3930 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003931 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303932 pthread_mutex_lock(&out->compr_mute_lock);
3933 out->a2dp_compress_mute = false;
3934 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3935 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08003936 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
3937 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303938 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003939 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003940 }
3941
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003943 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003944 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003945 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003946
3947 if (out == adev->primary_output) {
3948 pthread_mutex_lock(&adev->lock);
3949 audio_extn_set_parameters(adev, parms);
3950 pthread_mutex_unlock(&adev->lock);
3951 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003952 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003953 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003954 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003955
3956 audio_extn_dts_create_state_notifier_node(out->usecase);
3957 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3958 popcount(out->channel_mask),
3959 out->playback_started);
3960
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003961 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003962 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003963
Surendar Karkaf51b5842018-04-26 11:28:38 +05303964 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
3965 sizeof(value));
3966 if (err >= 0) {
3967 if (!strncmp("true", value, sizeof("true")) || atoi(value))
3968 audio_extn_send_dual_mono_mixing_coefficients(out);
3969 }
3970
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303971 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3972 if (err >= 0) {
3973 strlcpy(out->profile, value, sizeof(out->profile));
3974 ALOGV("updating stream profile with value '%s'", out->profile);
3975 lock_output_stream(out);
3976 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3977 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07003978 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303979 out->sample_rate, out->bit_width,
3980 out->channel_mask, out->profile,
3981 &out->app_type_cfg);
3982 pthread_mutex_unlock(&out->lock);
3983 }
3984
Alexy Joseph98988832017-01-13 14:56:59 -08003985 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08003986 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
3987 // and vendor.audio.hal.output.suspend.supported is set to true
3988 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08003989 //check suspend parameter only for low latency and if the property
3990 //is enabled
3991 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3992 ALOGI("%s: got suspend_playback %s", __func__, value);
3993 lock_output_stream(out);
3994 if (!strncmp(value, "false", 5)) {
3995 //suspend_playback=false is supposed to set QOS value back to 75%
3996 //the mixer control sent with value Enable will achieve that
3997 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3998 } else if (!strncmp (value, "true", 4)) {
3999 //suspend_playback=true is supposed to remove QOS value
4000 //resetting the mixer control will set the default value
4001 //for the mixer control which is Disable and this removes the QOS vote
4002 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4003 } else {
4004 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4005 " got %s", __func__, value);
4006 ret = -1;
4007 }
4008
4009 if (ret != 0) {
4010 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4011 __func__, out->pm_qos_mixer_path, ret);
4012 }
4013
4014 pthread_mutex_unlock(&out->lock);
4015 }
4016 }
4017 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004018 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304019error:
Eric Laurent994a6932013-07-17 11:51:42 -07004020 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004021 return ret;
4022}
4023
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004024static bool stream_get_parameter_channels(struct str_parms *query,
4025 struct str_parms *reply,
4026 audio_channel_mask_t *supported_channel_masks) {
4027 int ret = -1;
4028 char value[512];
4029 bool first = true;
4030 size_t i, j;
4031
4032 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4033 ret = 0;
4034 value[0] = '\0';
4035 i = 0;
4036 while (supported_channel_masks[i] != 0) {
4037 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4038 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4039 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304040 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004041
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304042 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004043 first = false;
4044 break;
4045 }
4046 }
4047 i++;
4048 }
4049 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4050 }
4051 return ret == 0;
4052}
4053
4054static bool stream_get_parameter_formats(struct str_parms *query,
4055 struct str_parms *reply,
4056 audio_format_t *supported_formats) {
4057 int ret = -1;
4058 char value[256];
4059 size_t i, j;
4060 bool first = true;
4061
4062 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4063 ret = 0;
4064 value[0] = '\0';
4065 i = 0;
4066 while (supported_formats[i] != 0) {
4067 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4068 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4069 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304070 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004071 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304072 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004073 first = false;
4074 break;
4075 }
4076 }
4077 i++;
4078 }
4079 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4080 }
4081 return ret == 0;
4082}
4083
4084static bool stream_get_parameter_rates(struct str_parms *query,
4085 struct str_parms *reply,
4086 uint32_t *supported_sample_rates) {
4087
4088 int i;
4089 char value[256];
4090 int ret = -1;
4091 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4092 ret = 0;
4093 value[0] = '\0';
4094 i=0;
4095 int cursor = 0;
4096 while (supported_sample_rates[i]) {
4097 int avail = sizeof(value) - cursor;
4098 ret = snprintf(value + cursor, avail, "%s%d",
4099 cursor > 0 ? "|" : "",
4100 supported_sample_rates[i]);
4101 if (ret < 0 || ret >= avail) {
4102 // if cursor is at the last element of the array
4103 // overwrite with \0 is duplicate work as
4104 // snprintf already put a \0 in place.
4105 // else
4106 // we had space to write the '|' at value[cursor]
4107 // (which will be overwritten) or no space to fill
4108 // the first element (=> cursor == 0)
4109 value[cursor] = '\0';
4110 break;
4111 }
4112 cursor += ret;
4113 ++i;
4114 }
4115 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4116 value);
4117 }
4118 return ret >= 0;
4119}
4120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4122{
4123 struct stream_out *out = (struct stream_out *)stream;
4124 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004125 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004126 char value[256];
4127 struct str_parms *reply = str_parms_create();
4128 size_t i, j;
4129 int ret;
4130 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004131
4132 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004133 if (reply) {
4134 str_parms_destroy(reply);
4135 }
4136 if (query) {
4137 str_parms_destroy(query);
4138 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004139 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4140 return NULL;
4141 }
4142
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004143 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004144 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4145 if (ret >= 0) {
4146 value[0] = '\0';
4147 i = 0;
4148 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004149 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4150 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004151 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004152 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004153 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004154 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004155 first = false;
4156 break;
4157 }
4158 }
4159 i++;
4160 }
4161 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4162 str = str_parms_to_str(reply);
4163 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004164 voice_extn_out_get_parameters(out, query, reply);
4165 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004166 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004167
Alexy Joseph62142aa2015-11-16 15:10:34 -08004168
4169 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4170 if (ret >= 0) {
4171 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304172 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4173 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004174 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304175 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004176 } else {
4177 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304178 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004179 }
4180 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004181 if (str)
4182 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004183 str = str_parms_to_str(reply);
4184 }
4185
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004186 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4187 if (ret >= 0) {
4188 value[0] = '\0';
4189 i = 0;
4190 first = true;
4191 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004192 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4193 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004194 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004195 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004196 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004197 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004198 first = false;
4199 break;
4200 }
4201 }
4202 i++;
4203 }
4204 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004205 if (str)
4206 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004207 str = str_parms_to_str(reply);
4208 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004209
4210 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4211 if (ret >= 0) {
4212 value[0] = '\0';
4213 i = 0;
4214 first = true;
4215 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004216 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4217 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004218 if (!first) {
4219 strlcat(value, "|", sizeof(value));
4220 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004221 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004222 first = false;
4223 break;
4224 }
4225 }
4226 i++;
4227 }
4228 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4229 if (str)
4230 free(str);
4231 str = str_parms_to_str(reply);
4232 }
4233
Alexy Joseph98988832017-01-13 14:56:59 -08004234 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4235 //only low latency track supports suspend_resume
4236 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004237 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004238 if (str)
4239 free(str);
4240 str = str_parms_to_str(reply);
4241 }
4242
4243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004244 str_parms_destroy(query);
4245 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004246 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247 return str;
4248}
4249
4250static uint32_t out_get_latency(const struct audio_stream_out *stream)
4251{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004252 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004253 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004254 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004255
Alexy Josephaa54c872014-12-03 02:46:47 -08004256 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304257 lock_output_stream(out);
4258 latency = audio_extn_utils_compress_get_dsp_latency(out);
4259 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004260 } else if ((out->realtime) ||
4261 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004262 // since the buffer won't be filled up faster than realtime,
4263 // return a smaller number
4264 if (out->config.rate)
4265 period_ms = (out->af_period_multiplier * out->config.period_size *
4266 1000) / (out->config.rate);
4267 else
4268 period_ms = 0;
4269 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004270 } else {
4271 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004272 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004273 }
4274
yidongh0515e042017-07-06 15:00:34 +08004275 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004276 latency += audio_extn_a2dp_get_encoder_latency();
4277
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304278 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004279 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004280}
4281
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304282static float AmpToDb(float amplification)
4283{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304284 float db = DSD_VOLUME_MIN_DB;
4285 if (amplification > 0) {
4286 db = 20 * log10(amplification);
4287 if(db < DSD_VOLUME_MIN_DB)
4288 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304289 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304290 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304291}
4292
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304293static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4294 float right)
4295{
4296 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304297 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304298 char mixer_ctl_name[128];
4299 struct audio_device *adev = out->dev;
4300 struct mixer_ctl *ctl;
4301 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4302 PCM_PLAYBACK);
4303
4304 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4305 "Compress Playback %d Volume", pcm_device_id);
4306 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4307 if (!ctl) {
4308 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4309 __func__, mixer_ctl_name);
4310 return -EINVAL;
4311 }
4312 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4313 __func__, mixer_ctl_name, left, right);
4314 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4315 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4316 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4317
4318 return 0;
4319}
4320
Zhou Song2b8f28f2017-09-11 10:51:38 +08004321static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4322 float right)
4323{
4324 struct stream_out *out = (struct stream_out *)stream;
4325 char mixer_ctl_name[] = "App Type Gain";
4326 struct audio_device *adev = out->dev;
4327 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304328 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004329
4330 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4331 if (!ctl) {
4332 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4333 __func__, mixer_ctl_name);
4334 return -EINVAL;
4335 }
4336
4337 set_values[0] = 0; //0: Rx Session 1:Tx Session
4338 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304339 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4340 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004341
4342 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4343 return 0;
4344}
4345
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304346static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
4347 float right)
4348{
4349 struct stream_out *out = (struct stream_out *)stream;
4350 /* Volume control for pcm playback */
4351 if (left != right) {
4352 return -EINVAL;
4353 } else {
4354 char mixer_ctl_name[128];
4355 struct audio_device *adev = out->dev;
4356 struct mixer_ctl *ctl;
4357 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4358 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
4359 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4360 if (!ctl) {
4361 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
4362 return -EINVAL;
4363 }
4364
4365 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
4366 int ret = mixer_ctl_set_value(ctl, 0, volume);
4367 if (ret < 0) {
4368 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
4369 return -EINVAL;
4370 }
4371
4372 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
4373
4374 return 0;
4375 }
4376}
4377
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004378static int out_set_volume(struct audio_stream_out *stream, float left,
4379 float right)
4380{
Eric Laurenta9024de2013-04-04 09:19:12 -07004381 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004382 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304383 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004384
Eric Laurenta9024de2013-04-04 09:19:12 -07004385 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4386 /* only take left channel into account: the API is for stereo anyway */
4387 out->muted = (left == 0.0f);
4388 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004389 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304390 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004391 /*
4392 * Set mute or umute on HDMI passthrough stream.
4393 * Only take left channel into account.
4394 * Mute is 0 and unmute 1
4395 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304396 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304397 } else if (out->format == AUDIO_FORMAT_DSD){
4398 char mixer_ctl_name[128] = "DSD Volume";
4399 struct audio_device *adev = out->dev;
4400 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4401
4402 if (!ctl) {
4403 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4404 __func__, mixer_ctl_name);
4405 return -EINVAL;
4406 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304407 volume[0] = (long)(AmpToDb(left));
4408 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304409 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4410 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004411 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304412 pthread_mutex_lock(&out->compr_mute_lock);
4413 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
4414 if (!out->a2dp_compress_mute)
4415 ret = out_set_compr_volume(stream, left, right);
4416 out->volume_l = left;
4417 out->volume_r = right;
4418 pthread_mutex_unlock(&out->compr_mute_lock);
4419 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004420 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004421 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004422 if (!out->standby)
4423 ret = out_set_voip_volume(stream, left, right);
4424 out->volume_l = left;
4425 out->volume_r = right;
4426 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304427 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
4428 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) {
4429 /* Volume control for pcm playback */
4430 if (!out->standby)
4431 ret = out_set_pcm_volume(stream, left, right);
4432 else
4433 out->apply_volume = true;
4434
4435 out->volume_l = left;
4436 out->volume_r = right;
4437 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004438 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004440 return -ENOSYS;
4441}
4442
Zhou Songc9672822017-08-16 16:01:39 +08004443static void update_frames_written(struct stream_out *out, size_t bytes)
4444{
4445 size_t bpf = 0;
4446
4447 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4448 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4449 bpf = 1;
4450 else if (!is_offload_usecase(out->usecase))
4451 bpf = audio_bytes_per_sample(out->format) *
4452 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004453
4454 pthread_mutex_lock(&out->position_query_lock);
4455 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004456 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004457 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4458 }
4459 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004460}
4461
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004462static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4463 size_t bytes)
4464{
4465 struct stream_out *out = (struct stream_out *)stream;
4466 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004467 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304468 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004469 const size_t frame_size = audio_stream_out_frame_size(stream);
4470 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004471
Haynes Mathew George380745d2017-10-04 15:27:45 -07004472 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004473 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304474
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304475 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004476
Dhananjay Kumarac341582017-02-23 23:42:25 +05304477 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304478 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304479 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4480 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004481 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304482 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304483 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304484 ALOGD(" %s: sound card is not active/SSR state", __func__);
4485 ret= -EIO;
4486 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304487 }
4488 }
4489
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304490 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304491 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304492 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304493 goto exit;
4494 }
4495
Haynes Mathew George16081042017-05-31 17:16:49 -07004496 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4497 ret = -EINVAL;
4498 goto exit;
4499 }
4500
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304501 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4502 !out->is_iec61937_info_available) {
4503
4504 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4505 out->is_iec61937_info_available = true;
4506 } else if (audio_extn_passthru_is_enabled()) {
4507 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304508 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304509
4510 if((out->format == AUDIO_FORMAT_DTS) ||
4511 (out->format == AUDIO_FORMAT_DTS_HD)) {
4512 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4513 buffer, bytes);
4514 if (ret) {
4515 if (ret != -ENOSYS) {
4516 out->is_iec61937_info_available = false;
4517 ALOGD("iec61937 transmission info not yet updated retry");
4518 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304519 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304520 /* if stream has started and after that there is
4521 * stream config change (iec transmission config)
4522 * then trigger select_device to update backend configuration.
4523 */
4524 out->stream_config_changed = true;
4525 pthread_mutex_lock(&adev->lock);
4526 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304527 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4528 ret = -EINVAL;
4529 goto exit;
4530 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304531 pthread_mutex_unlock(&adev->lock);
4532 out->stream_config_changed = false;
4533 out->is_iec61937_info_available = true;
4534 }
4535 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304536
Garmond Leung317cbf12017-09-13 16:20:50 -07004537 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304538 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4539 (out->is_iec61937_info_available == true)) {
4540 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4541 ret = -EINVAL;
4542 goto exit;
4543 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304544 }
4545 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304546
4547 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4548 (audio_extn_a2dp_is_suspended())) {
4549 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4550 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304551 ret = -EIO;
4552 goto exit;
4553 }
4554 }
4555 }
4556
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004558 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004559 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004560 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4561 ret = voice_extn_compress_voip_start_output_stream(out);
4562 else
4563 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004564 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004565 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004566 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004567 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004568 goto exit;
4569 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304570 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004571 if (last_known_cal_step != -1) {
4572 ALOGD("%s: retry previous failed cal level set", __func__);
4573 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304574 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004575 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304576
4577 if ((out->is_iec61937_info_available == true) &&
4578 (audio_extn_passthru_is_passthrough_stream(out))&&
4579 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4580 ret = -EINVAL;
4581 goto exit;
4582 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05304583 if (out->set_dual_mono)
4584 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004585 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004586
Ashish Jain81eb2a82015-05-13 10:52:34 +05304587 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004588 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304589 adev->is_channel_status_set = true;
4590 }
4591
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004592 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004593 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004594 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004595 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004596 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4597 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304598 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4599 ALOGD("copl(%p):send next track params in gapless", out);
4600 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4601 out->send_next_track_params = false;
4602 out->is_compr_metadata_avail = false;
4603 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004604 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304605 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304606 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004607
Ashish Jain83a6cc22016-06-28 14:34:17 +05304608 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304609 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304610 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304611 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004612 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304613 return -EINVAL;
4614 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304615 audio_format_t dst_format = out->hal_op_format;
4616 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304617
4618 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4619 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4620
Ashish Jain83a6cc22016-06-28 14:34:17 +05304621 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304622 dst_format,
4623 buffer,
4624 src_format,
4625 frames);
4626
Ashish Jain83a6cc22016-06-28 14:34:17 +05304627 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304628 bytes_to_write);
4629
4630 /*Convert written bytes in audio flinger format*/
4631 if (ret > 0)
4632 ret = ((ret * format_to_bitwidth_table[out->format]) /
4633 format_to_bitwidth_table[dst_format]);
4634 }
4635 } else
4636 ret = compress_write(out->compr, buffer, bytes);
4637
Zhou Songc9672822017-08-16 16:01:39 +08004638 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4639 update_frames_written(out, bytes);
4640
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304641 if (ret < 0)
4642 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08004643 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304644 /*msg to cb thread only if non blocking write is enabled*/
4645 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304646 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004647 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304648 } else if (-ENETRESET == ret) {
4649 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304650 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304651 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304652 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004653 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304654 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004655 }
Ashish Jain5106d362016-05-11 19:23:33 +05304656
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304657 /* Call compr start only when non-zero bytes of data is there to be rendered */
4658 if (!out->playback_started && ret > 0) {
4659 int status = compress_start(out->compr);
4660 if (status < 0) {
4661 ret = status;
4662 ALOGE("%s: compr start failed with err %d", __func__, errno);
4663 goto exit;
4664 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004665 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004666 out->playback_started = 1;
4667 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004668
4669 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4670 popcount(out->channel_mask),
4671 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004672 }
4673 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004674 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004675 return ret;
4676 } else {
4677 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004678 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004679 if (out->muted)
4680 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004681 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
4682 __func__, frames, frame_size, bytes_to_write);
4683
4684 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
4685 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4686 int16_t *src = (int16_t *)buffer;
4687 int16_t *dst = (int16_t *)buffer;
4688
4689 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
4690 out->format != AUDIO_FORMAT_PCM_16_BIT,
4691 "out_write called for incall music use case with wrong properties");
4692
4693 /*
4694 * FIXME: this can be removed once audio flinger mixer supports
4695 * mono output
4696 */
4697
4698 /*
4699 * Code below goes over each frame in the buffer and adds both
4700 * L and R samples and then divides by 2 to convert to mono
4701 */
4702 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
4703 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
4704 }
4705 bytes_to_write /= 2;
4706 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004707
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304708 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004709
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004710 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004711
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004712 if (out->config.rate)
4713 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4714 out->config.rate;
4715
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004716 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004717 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4718
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004719 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004720 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004721 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304722 out->convert_buffer != NULL) {
4723
4724 memcpy_by_audio_format(out->convert_buffer,
4725 out->hal_op_format,
4726 buffer,
4727 out->hal_ip_format,
4728 out->config.period_size * out->config.channels);
4729
4730 ret = pcm_write(out->pcm, out->convert_buffer,
4731 (out->config.period_size *
4732 out->config.channels *
4733 format_to_bitwidth_table[out->hal_op_format]));
4734 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304735 /*
4736 * To avoid underrun in DSP when the application is not pumping
4737 * data at required rate, check for the no. of bytes and ignore
4738 * pcm_write if it is less than actual buffer size.
4739 * It is a work around to a change in compress VOIP driver.
4740 */
4741 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4742 bytes < (out->config.period_size * out->config.channels *
4743 audio_bytes_per_sample(out->format))) {
4744 size_t voip_buf_size =
4745 out->config.period_size * out->config.channels *
4746 audio_bytes_per_sample(out->format);
4747 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4748 __func__, bytes, voip_buf_size);
4749 usleep(((uint64_t)voip_buf_size - bytes) *
4750 1000000 / audio_stream_out_frame_size(stream) /
4751 out_get_sample_rate(&out->stream.common));
4752 ret = 0;
4753 } else
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004754 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304755 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004756
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004757 release_out_focus(out);
4758
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304759 if (ret < 0)
4760 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004761 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304762 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004763 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004764 }
4765
4766exit:
Zhou Songc9672822017-08-16 16:01:39 +08004767 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304768 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304769 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304770 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004771 pthread_mutex_unlock(&out->lock);
4772
4773 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004774 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004775 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304776 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304777 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304778 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304779 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304780 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304781 out->standby = true;
4782 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304783 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304784 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4785 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4786 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004787
4788 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05304789 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004790 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004791 return ret;
4792 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004793 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004794 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004795 return bytes;
4796}
4797
4798static int out_get_render_position(const struct audio_stream_out *stream,
4799 uint32_t *dsp_frames)
4800{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004801 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004802
4803 if (dsp_frames == NULL)
4804 return -EINVAL;
4805
4806 *dsp_frames = 0;
4807 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004808 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304809
4810 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4811 * this operation and adev_close_output_stream(where out gets reset).
4812 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304813 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004814 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05304815 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004816 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304817 return 0;
4818 }
4819
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004820 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304821 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304822 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004823 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304824 if (ret < 0)
4825 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004826 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304827 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004828 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304829 if (-ENETRESET == ret) {
4830 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304831 out->card_status = CARD_STATUS_OFFLINE;
4832 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304833 } else if(ret < 0) {
4834 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304835 ret = -EINVAL;
4836 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304837 /*
4838 * Handle corner case where compress session is closed during SSR
4839 * and timestamp is queried
4840 */
4841 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304842 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304843 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304844 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004845 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05304846 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304847 pthread_mutex_unlock(&out->lock);
4848 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004849 } else if (audio_is_linear_pcm(out->format)) {
4850 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004851 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08004852 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004853 } else
4854 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004855}
4856
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004857static int out_add_audio_effect(const struct audio_stream *stream __unused,
4858 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004859{
4860 return 0;
4861}
4862
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004863static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4864 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004865{
4866 return 0;
4867}
4868
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004869static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4870 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004871{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304872 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004873}
4874
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004875static int out_get_presentation_position(const struct audio_stream_out *stream,
4876 uint64_t *frames, struct timespec *timestamp)
4877{
4878 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05304879 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07004880 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004881
Ashish Jain5106d362016-05-11 19:23:33 +05304882 /* below piece of code is not guarded against any lock because audioFliner serializes
4883 * this operation and adev_close_output_stream( where out gets reset).
4884 */
4885 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304886 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004887 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05304888 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4889 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4890 return 0;
4891 }
4892
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004893 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004894
Ashish Jain5106d362016-05-11 19:23:33 +05304895 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4896 ret = compress_get_tstamp(out->compr, &dsp_frames,
4897 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004898 // Adjustment accounts for A2dp encoder latency with offload usecases
4899 // Note: Encoder latency is returned in ms.
4900 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4901 unsigned long offset =
4902 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4903 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4904 }
Ashish Jain5106d362016-05-11 19:23:33 +05304905 ALOGVV("%s rendered frames %ld sample_rate %d",
4906 __func__, dsp_frames, out->sample_rate);
4907 *frames = dsp_frames;
4908 if (ret < 0)
4909 ret = -errno;
4910 if (-ENETRESET == ret) {
4911 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304912 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304913 ret = -EINVAL;
4914 } else
4915 ret = 0;
4916 /* this is the best we can do */
4917 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07004918 } else {
4919 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08004920 unsigned int avail;
4921 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
4922 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
4923 int64_t signed_frames = out->written - kernel_buffer_size + avail;
4924 // This adjustment accounts for buffering after app processor.
4925 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07004926 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08004927 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07004928
Weiyin Jiangd4633762018-03-16 12:05:03 +08004929 // Adjustment accounts for A2dp encoder latency with non offload usecases
4930 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
4931 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4932 signed_frames -=
4933 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4934 }
4935
4936 // It would be unusual for this value to be negative, but check just in case ...
4937 if (signed_frames >= 0) {
4938 *frames = signed_frames;
4939 ret = 0;
4940 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004941 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304942 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304943 *frames = out->written;
4944 clock_gettime(CLOCK_MONOTONIC, timestamp);
4945 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004946 }
4947 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004948 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004949 return ret;
4950}
4951
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004952static int out_set_callback(struct audio_stream_out *stream,
4953 stream_callback_t callback, void *cookie)
4954{
4955 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004956 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004957
4958 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004959 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004960 out->client_callback = callback;
4961 out->client_cookie = cookie;
4962 if (out->adsp_hdlr_stream_handle) {
4963 ret = audio_extn_adsp_hdlr_stream_set_callback(
4964 out->adsp_hdlr_stream_handle,
4965 callback,
4966 cookie);
4967 if (ret)
4968 ALOGW("%s:adsp hdlr callback registration failed %d",
4969 __func__, ret);
4970 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004971 pthread_mutex_unlock(&out->lock);
4972 return 0;
4973}
4974
4975static int out_pause(struct audio_stream_out* stream)
4976{
4977 struct stream_out *out = (struct stream_out *)stream;
4978 int status = -ENOSYS;
4979 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004980 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004981 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004982 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004983 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304984 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304985 status = compress_pause(out->compr);
4986
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004987 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004988
Mingming Yin21854652016-04-13 11:54:02 -07004989 if (audio_extn_passthru_is_active()) {
4990 ALOGV("offload use case, pause passthru");
4991 audio_extn_passthru_on_pause(out);
4992 }
4993
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304994 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004995 audio_extn_dts_notify_playback_state(out->usecase, 0,
4996 out->sample_rate, popcount(out->channel_mask),
4997 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004998 }
4999 pthread_mutex_unlock(&out->lock);
5000 }
5001 return status;
5002}
5003
5004static int out_resume(struct audio_stream_out* stream)
5005{
5006 struct stream_out *out = (struct stream_out *)stream;
5007 int status = -ENOSYS;
5008 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005009 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005010 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005011 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005012 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005013 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305014 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305015 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005016 }
5017 if (!status) {
5018 out->offload_state = OFFLOAD_STATE_PLAYING;
5019 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305020 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005021 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5022 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005023 }
5024 pthread_mutex_unlock(&out->lock);
5025 }
5026 return status;
5027}
5028
5029static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5030{
5031 struct stream_out *out = (struct stream_out *)stream;
5032 int status = -ENOSYS;
5033 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005034 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005035 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005036 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5037 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5038 else
5039 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5040 pthread_mutex_unlock(&out->lock);
5041 }
5042 return status;
5043}
5044
5045static int out_flush(struct audio_stream_out* stream)
5046{
5047 struct stream_out *out = (struct stream_out *)stream;
5048 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005049 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005050 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005051 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005052 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5053 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005054 } else {
5055 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5056 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005057 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005058 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005059 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005060 return 0;
5061 }
5062 return -ENOSYS;
5063}
5064
Haynes Mathew George16081042017-05-31 17:16:49 -07005065static int out_stop(const struct audio_stream_out* stream)
5066{
5067 struct stream_out *out = (struct stream_out *)stream;
5068 struct audio_device *adev = out->dev;
5069 int ret = -ENOSYS;
5070
5071 ALOGV("%s", __func__);
5072 pthread_mutex_lock(&adev->lock);
5073 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5074 out->playback_started && out->pcm != NULL) {
5075 pcm_stop(out->pcm);
5076 ret = stop_output_stream(out);
5077 out->playback_started = false;
5078 }
5079 pthread_mutex_unlock(&adev->lock);
5080 return ret;
5081}
5082
5083static int out_start(const struct audio_stream_out* stream)
5084{
5085 struct stream_out *out = (struct stream_out *)stream;
5086 struct audio_device *adev = out->dev;
5087 int ret = -ENOSYS;
5088
5089 ALOGV("%s", __func__);
5090 pthread_mutex_lock(&adev->lock);
5091 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5092 !out->playback_started && out->pcm != NULL) {
5093 ret = start_output_stream(out);
5094 if (ret == 0) {
5095 out->playback_started = true;
5096 }
5097 }
5098 pthread_mutex_unlock(&adev->lock);
5099 return ret;
5100}
5101
5102/*
5103 * Modify config->period_count based on min_size_frames
5104 */
5105static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5106{
5107 int periodCountRequested = (min_size_frames + config->period_size - 1)
5108 / config->period_size;
5109 int periodCount = MMAP_PERIOD_COUNT_MIN;
5110
5111 ALOGV("%s original config.period_size = %d config.period_count = %d",
5112 __func__, config->period_size, config->period_count);
5113
5114 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5115 periodCount *= 2;
5116 }
5117 config->period_count = periodCount;
5118
5119 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5120}
5121
5122static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5123 int32_t min_size_frames,
5124 struct audio_mmap_buffer_info *info)
5125{
5126 struct stream_out *out = (struct stream_out *)stream;
5127 struct audio_device *adev = out->dev;
5128 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005129 unsigned int offset1 = 0;
5130 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005131 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005132 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005133
5134 ALOGV("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305135 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005136 pthread_mutex_lock(&adev->lock);
5137
Sharad Sanglec6f32552018-05-04 16:15:38 +05305138 if (CARD_STATUS_OFFLINE == out->card_status ||
5139 CARD_STATUS_OFFLINE == adev->card_status) {
5140 ALOGW("out->card_status or adev->card_status offline, try again");
5141 ret = -EIO;
5142 goto exit;
5143 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005144 if (info == NULL || min_size_frames == 0) {
5145 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5146 ret = -EINVAL;
5147 goto exit;
5148 }
5149 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5150 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5151 ret = -ENOSYS;
5152 goto exit;
5153 }
5154 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5155 if (out->pcm_device_id < 0) {
5156 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5157 __func__, out->pcm_device_id, out->usecase);
5158 ret = -EINVAL;
5159 goto exit;
5160 }
5161
5162 adjust_mmap_period_count(&out->config, min_size_frames);
5163
5164 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5165 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5166 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5167 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305168 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305169 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5170 out->card_status = CARD_STATUS_OFFLINE;
5171 adev->card_status = CARD_STATUS_OFFLINE;
5172 ret = -EIO;
5173 goto exit;
5174 }
5175
Haynes Mathew George16081042017-05-31 17:16:49 -07005176 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5177 step = "open";
5178 ret = -ENODEV;
5179 goto exit;
5180 }
5181 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5182 if (ret < 0) {
5183 step = "begin";
5184 goto exit;
5185 }
5186 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
5187 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005188 ret = platform_get_mmap_data_fd(adev->platform,
5189 out->pcm_device_id, 0 /*playback*/,
5190 &info->shared_memory_fd,
5191 &mmap_size);
5192 if (ret < 0) {
5193 step = "get_mmap_fd";
5194 goto exit;
5195 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005196 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005197 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005198
5199 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5200 if (ret < 0) {
5201 step = "commit";
5202 goto exit;
5203 }
5204
5205 out->standby = false;
5206 ret = 0;
5207
5208 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5209 __func__, info->shared_memory_address, info->buffer_size_frames);
5210
5211exit:
5212 if (ret != 0) {
5213 if (out->pcm == NULL) {
5214 ALOGE("%s: %s - %d", __func__, step, ret);
5215 } else {
5216 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5217 pcm_close(out->pcm);
5218 out->pcm = NULL;
5219 }
5220 }
5221 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305222 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005223 return ret;
5224}
5225
5226static int out_get_mmap_position(const struct audio_stream_out *stream,
5227 struct audio_mmap_position *position)
5228{
5229 struct stream_out *out = (struct stream_out *)stream;
5230 ALOGVV("%s", __func__);
5231 if (position == NULL) {
5232 return -EINVAL;
5233 }
5234 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005235 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005236 return -ENOSYS;
5237 }
5238 if (out->pcm == NULL) {
5239 return -ENOSYS;
5240 }
5241
5242 struct timespec ts = { 0, 0 };
5243 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5244 if (ret < 0) {
5245 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5246 return ret;
5247 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005248 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005249 return 0;
5250}
5251
5252
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005253/** audio_stream_in implementation **/
5254static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5255{
5256 struct stream_in *in = (struct stream_in *)stream;
5257
5258 return in->config.rate;
5259}
5260
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005261static int in_set_sample_rate(struct audio_stream *stream __unused,
5262 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005263{
5264 return -ENOSYS;
5265}
5266
5267static size_t in_get_buffer_size(const struct audio_stream *stream)
5268{
5269 struct stream_in *in = (struct stream_in *)stream;
5270
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005271 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5272 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005273 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5274 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 -07005275 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5276 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305277 else if(audio_extn_cin_attached_usecase(in->usecase))
5278 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005279
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005280 return in->config.period_size * in->af_period_multiplier *
5281 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005282}
5283
5284static uint32_t in_get_channels(const struct audio_stream *stream)
5285{
5286 struct stream_in *in = (struct stream_in *)stream;
5287
5288 return in->channel_mask;
5289}
5290
5291static audio_format_t in_get_format(const struct audio_stream *stream)
5292{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005293 struct stream_in *in = (struct stream_in *)stream;
5294
5295 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005296}
5297
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005298static int in_set_format(struct audio_stream *stream __unused,
5299 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005300{
5301 return -ENOSYS;
5302}
5303
5304static int in_standby(struct audio_stream *stream)
5305{
5306 struct stream_in *in = (struct stream_in *)stream;
5307 struct audio_device *adev = in->dev;
5308 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305309 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5310 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005311 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305312
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005313 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005314 if (!in->standby && in->is_st_session) {
5315 ALOGD("%s: sound trigger pcm stop lab", __func__);
5316 audio_extn_sound_trigger_stop_lab(in);
5317 in->standby = 1;
5318 }
5319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005320 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005321 if (adev->adm_deregister_stream)
5322 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5323
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005324 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005325 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005326 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005327 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005328 voice_extn_compress_voip_close_input_stream(stream);
5329 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005330 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5331 do_stop = in->capture_started;
5332 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005333 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305334 if (audio_extn_cin_attached_usecase(in->usecase))
5335 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005336 }
5337
5338 if (do_stop) {
Zhou Songa8895042016-07-05 17:54:22 +08005339 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005340 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005341 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005342 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005343 in->pcm = NULL;
5344 }
5345 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005346 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08005347 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005348 }
5349 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005350 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005351 return status;
5352}
5353
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005354static int in_dump(const struct audio_stream *stream __unused,
5355 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005356{
5357 return 0;
5358}
5359
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305360static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5361{
5362 if (!stream || !parms)
5363 return;
5364
5365 struct stream_in *in = (struct stream_in *)stream;
5366 struct audio_device *adev = in->dev;
5367
5368 card_status_t status;
5369 int card;
5370 if (parse_snd_card_status(parms, &card, &status) < 0)
5371 return;
5372
5373 pthread_mutex_lock(&adev->lock);
5374 bool valid_cb = (card == adev->snd_card);
5375 pthread_mutex_unlock(&adev->lock);
5376
5377 if (!valid_cb)
5378 return;
5379
5380 lock_input_stream(in);
5381 if (in->card_status != status)
5382 in->card_status = status;
5383 pthread_mutex_unlock(&in->lock);
5384
5385 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5386 use_case_table[in->usecase],
5387 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5388
5389 // a better solution would be to report error back to AF and let
5390 // it put the stream to standby
5391 if (status == CARD_STATUS_OFFLINE)
5392 in_standby(&in->stream.common);
5393
5394 return;
5395}
5396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005397static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5398{
5399 struct stream_in *in = (struct stream_in *)stream;
5400 struct audio_device *adev = in->dev;
5401 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005402 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005403 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005404
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305405 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005406 parms = str_parms_create_str(kvpairs);
5407
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305408 if (!parms)
5409 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005410 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005411 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005412
5413 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5414 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005415 val = atoi(value);
5416 /* no audio source uses val == 0 */
5417 if ((in->source != val) && (val != 0)) {
5418 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005419 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5420 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5421 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005422 (in->config.rate == 8000 || in->config.rate == 16000 ||
5423 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005424 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005425 err = voice_extn_compress_voip_open_input_stream(in);
5426 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005427 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005428 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005429 }
5430 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005431 }
5432 }
5433
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005434 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5435 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005436 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005437 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5438
5439 // Workaround: If routing to an non existing usb device, fail gracefully
5440 // The routing request will otherwise block during 10 second
5441 int card;
5442 if (audio_is_usb_in_device(val) &&
5443 (card = get_alive_usb_card(parms)) >= 0) {
5444
5445 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5446 ret = -ENOSYS;
5447 } else {
5448
5449 in->device = val;
5450 /* If recording is in progress, change the tx device to new device */
5451 if (!in->standby && !in->is_st_session) {
5452 ALOGV("update input routing change");
5453 // inform adm before actual routing to prevent glitches.
5454 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005455 adev->adm_on_routing_change(adev->adm_data,
5456 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005457 ret = select_devices(adev, in->usecase);
5458 }
5459 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005460 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005461 }
5462 }
5463
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305464 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5465 if (err >= 0) {
5466 strlcpy(in->profile, value, sizeof(in->profile));
5467 ALOGV("updating stream profile with value '%s'", in->profile);
5468 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5469 &adev->streams_input_cfg_list,
5470 in->device, in->flags, in->format,
5471 in->sample_rate, in->bit_width,
5472 in->profile, &in->app_type_cfg);
5473 }
5474
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005475 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005476 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005477
5478 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305479error:
Eric Laurent994a6932013-07-17 11:51:42 -07005480 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005481 return ret;
5482}
5483
5484static char* in_get_parameters(const struct audio_stream *stream,
5485 const char *keys)
5486{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005487 struct stream_in *in = (struct stream_in *)stream;
5488 struct str_parms *query = str_parms_create_str(keys);
5489 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005490 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005491
5492 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005493 if (reply) {
5494 str_parms_destroy(reply);
5495 }
5496 if (query) {
5497 str_parms_destroy(query);
5498 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005499 ALOGE("in_get_parameters: failed to create query or reply");
5500 return NULL;
5501 }
5502
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005503 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005504
5505 voice_extn_in_get_parameters(in, query, reply);
5506
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005507 stream_get_parameter_channels(query, reply,
5508 &in->supported_channel_masks[0]);
5509 stream_get_parameter_formats(query, reply,
5510 &in->supported_formats[0]);
5511 stream_get_parameter_rates(query, reply,
5512 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005513 str = str_parms_to_str(reply);
5514 str_parms_destroy(query);
5515 str_parms_destroy(reply);
5516
5517 ALOGV("%s: exit: returns - %s", __func__, str);
5518 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005519}
5520
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005521static int in_set_gain(struct audio_stream_in *stream __unused,
5522 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005523{
5524 return 0;
5525}
5526
5527static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5528 size_t bytes)
5529{
5530 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305531
5532 if (in == NULL) {
5533 ALOGE("%s: stream_in ptr is NULL", __func__);
5534 return -EINVAL;
5535 }
5536
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005537 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305538 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305539 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005540
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005541 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305542
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005543 if (in->is_st_session) {
5544 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5545 /* Read from sound trigger HAL */
5546 audio_extn_sound_trigger_read(in, buffer, bytes);
5547 pthread_mutex_unlock(&in->lock);
5548 return bytes;
5549 }
5550
Haynes Mathew George16081042017-05-31 17:16:49 -07005551 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5552 ret = -ENOSYS;
5553 goto exit;
5554 }
5555
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005556 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005557 pthread_mutex_lock(&adev->lock);
5558 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5559 ret = voice_extn_compress_voip_start_input_stream(in);
5560 else
5561 ret = start_input_stream(in);
5562 pthread_mutex_unlock(&adev->lock);
5563 if (ret != 0) {
5564 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005565 }
5566 in->standby = 0;
5567 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005568
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005569 // what's the duration requested by the client?
5570 long ns = 0;
5571
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305572 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005573 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5574 in->config.rate;
5575
5576 request_in_focus(in, ns);
5577 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005578
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305579 if (audio_extn_cin_attached_usecase(in->usecase)) {
5580 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5581 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305582 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005583 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305584 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005585 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005586 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005587 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005588 } else if (audio_extn_ffv_get_stream() == in) {
5589 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305590 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005591 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305592 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5593 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5594 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5595 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305596 ret = -EINVAL;
5597 goto exit;
5598 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305599 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305600 ret = -errno;
5601 }
5602 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305603 /* bytes read is always set to bytes for non compress usecases */
5604 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005605 }
5606
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005607 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005609 /*
5610 * Instead of writing zeroes here, we could trust the hardware
5611 * to always provide zeroes when muted.
5612 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305613 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5614 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005615 memset(buffer, 0, bytes);
5616
5617exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005618 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305619 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005620 pthread_mutex_unlock(&in->lock);
5621
5622 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305623 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305624 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305625 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305626 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305627 in->standby = true;
5628 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305629 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5630 bytes_read = bytes;
5631 memset(buffer, 0, bytes);
5632 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005633 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005634 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305635 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305636 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005637 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305638 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005639}
5640
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005641static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005642{
5643 return 0;
5644}
5645
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005646static int add_remove_audio_effect(const struct audio_stream *stream,
5647 effect_handle_t effect,
5648 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005649{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005650 struct stream_in *in = (struct stream_in *)stream;
5651 int status = 0;
5652 effect_descriptor_t desc;
5653
5654 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005655 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5656
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005657 if (status != 0)
5658 return status;
5659
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005660 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005661 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08005662 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5663 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005664 in->enable_aec != enable &&
5665 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5666 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005667 if (!in->standby) {
5668 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5669 select_devices(in->dev, in->usecase);
5670 }
5671
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005672 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005673 if (in->enable_ns != enable &&
5674 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5675 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005676 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08005677 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5678 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005679 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5680 select_devices(in->dev, in->usecase);
5681 } else
5682 select_devices(in->dev, in->usecase);
5683 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005684 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005685 pthread_mutex_unlock(&in->dev->lock);
5686 pthread_mutex_unlock(&in->lock);
5687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005688 return 0;
5689}
5690
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005691static int in_add_audio_effect(const struct audio_stream *stream,
5692 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005693{
Eric Laurent994a6932013-07-17 11:51:42 -07005694 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005695 return add_remove_audio_effect(stream, effect, true);
5696}
5697
5698static int in_remove_audio_effect(const struct audio_stream *stream,
5699 effect_handle_t effect)
5700{
Eric Laurent994a6932013-07-17 11:51:42 -07005701 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005702 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005703}
5704
Haynes Mathew George16081042017-05-31 17:16:49 -07005705static int in_stop(const struct audio_stream_in* stream)
5706{
5707 struct stream_in *in = (struct stream_in *)stream;
5708 struct audio_device *adev = in->dev;
5709
5710 int ret = -ENOSYS;
5711 ALOGV("%s", __func__);
5712 pthread_mutex_lock(&adev->lock);
5713 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5714 in->capture_started && in->pcm != NULL) {
5715 pcm_stop(in->pcm);
5716 ret = stop_input_stream(in);
5717 in->capture_started = false;
5718 }
5719 pthread_mutex_unlock(&adev->lock);
5720 return ret;
5721}
5722
5723static int in_start(const struct audio_stream_in* stream)
5724{
5725 struct stream_in *in = (struct stream_in *)stream;
5726 struct audio_device *adev = in->dev;
5727 int ret = -ENOSYS;
5728
5729 ALOGV("%s in %p", __func__, in);
5730 pthread_mutex_lock(&adev->lock);
5731 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5732 !in->capture_started && in->pcm != NULL) {
5733 if (!in->capture_started) {
5734 ret = start_input_stream(in);
5735 if (ret == 0) {
5736 in->capture_started = true;
5737 }
5738 }
5739 }
5740 pthread_mutex_unlock(&adev->lock);
5741 return ret;
5742}
5743
5744static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5745 int32_t min_size_frames,
5746 struct audio_mmap_buffer_info *info)
5747{
5748 struct stream_in *in = (struct stream_in *)stream;
5749 struct audio_device *adev = in->dev;
5750 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005751 unsigned int offset1 = 0;
5752 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005753 const char *step = "";
5754
5755 pthread_mutex_lock(&adev->lock);
5756 ALOGV("%s in %p", __func__, in);
5757
Sharad Sanglec6f32552018-05-04 16:15:38 +05305758 if (CARD_STATUS_OFFLINE == in->card_status||
5759 CARD_STATUS_OFFLINE == adev->card_status) {
5760 ALOGW("in->card_status or adev->card_status offline, try again");
5761 ret = -EIO;
5762 goto exit;
5763 }
5764
Haynes Mathew George16081042017-05-31 17:16:49 -07005765 if (info == NULL || min_size_frames == 0) {
5766 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5767 ret = -EINVAL;
5768 goto exit;
5769 }
5770 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5771 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5772 ALOGV("%s in %p", __func__, in);
5773 ret = -ENOSYS;
5774 goto exit;
5775 }
5776 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5777 if (in->pcm_device_id < 0) {
5778 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5779 __func__, in->pcm_device_id, in->usecase);
5780 ret = -EINVAL;
5781 goto exit;
5782 }
5783
5784 adjust_mmap_period_count(&in->config, min_size_frames);
5785
5786 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5787 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5788 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5789 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305790 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305791 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5792 in->card_status = CARD_STATUS_OFFLINE;
5793 adev->card_status = CARD_STATUS_OFFLINE;
5794 ret = -EIO;
5795 goto exit;
5796 }
5797
Haynes Mathew George16081042017-05-31 17:16:49 -07005798 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5799 step = "open";
5800 ret = -ENODEV;
5801 goto exit;
5802 }
5803
5804 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5805 if (ret < 0) {
5806 step = "begin";
5807 goto exit;
5808 }
5809 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5810 info->burst_size_frames = in->config.period_size;
5811 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
5812
5813 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
5814 info->buffer_size_frames));
5815
5816 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
5817 if (ret < 0) {
5818 step = "commit";
5819 goto exit;
5820 }
5821
5822 in->standby = false;
5823 ret = 0;
5824
5825 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5826 __func__, info->shared_memory_address, info->buffer_size_frames);
5827
5828exit:
5829 if (ret != 0) {
5830 if (in->pcm == NULL) {
5831 ALOGE("%s: %s - %d", __func__, step, ret);
5832 } else {
5833 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
5834 pcm_close(in->pcm);
5835 in->pcm = NULL;
5836 }
5837 }
5838 pthread_mutex_unlock(&adev->lock);
5839 return ret;
5840}
5841
5842static int in_get_mmap_position(const struct audio_stream_in *stream,
5843 struct audio_mmap_position *position)
5844{
5845 struct stream_in *in = (struct stream_in *)stream;
5846 ALOGVV("%s", __func__);
5847 if (position == NULL) {
5848 return -EINVAL;
5849 }
5850 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
5851 return -ENOSYS;
5852 }
5853 if (in->pcm == NULL) {
5854 return -ENOSYS;
5855 }
5856 struct timespec ts = { 0, 0 };
5857 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
5858 if (ret < 0) {
5859 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
5860 return ret;
5861 }
Naresh Tanniru119d74a2018-11-02 09:49:44 +05305862 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005863 return 0;
5864}
5865
Naresh Tannirudcb47c52018-06-25 16:23:32 +05305866static int in_get_active_microphones(const struct audio_stream_in *stream,
5867 struct audio_microphone_characteristic_t *mic_array,
5868 size_t *mic_count) {
5869 struct stream_in *in = (struct stream_in *)stream;
5870 struct audio_device *adev = in->dev;
5871 ALOGVV("%s", __func__);
5872
5873 lock_input_stream(in);
5874 pthread_mutex_lock(&adev->lock);
5875 int ret = platform_get_active_microphones(adev->platform,
5876 audio_channel_count_from_in_mask(in->channel_mask),
5877 in->usecase, mic_array, mic_count);
5878 pthread_mutex_unlock(&adev->lock);
5879 pthread_mutex_unlock(&in->lock);
5880
5881 return ret;
5882}
5883
5884static int adev_get_microphones(const struct audio_hw_device *dev,
5885 struct audio_microphone_characteristic_t *mic_array,
5886 size_t *mic_count) {
5887 struct audio_device *adev = (struct audio_device *)dev;
5888 ALOGVV("%s", __func__);
5889
5890 pthread_mutex_lock(&adev->lock);
5891 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
5892 pthread_mutex_unlock(&adev->lock);
5893
5894 return ret;
5895}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305896int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07005897 audio_io_handle_t handle,
5898 audio_devices_t devices,
5899 audio_output_flags_t flags,
5900 struct audio_config *config,
5901 struct audio_stream_out **stream_out,
5902 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005903{
5904 struct audio_device *adev = (struct audio_device *)dev;
5905 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305906 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005907 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005908 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05305909 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005910 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
5911 bool is_usb_dev = audio_is_usb_out_device(devices) &&
5912 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
5913 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005914
kunleizdff872d2018-08-20 14:40:33 +08005915 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08005916 is_usb_dev = false;
5917 devices = AUDIO_DEVICE_OUT_SPEAKER;
5918 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
5919 __func__, devices);
5920 }
5921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005922 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305923
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005924 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
5925
Mingming Yin3a941d42016-02-17 18:08:05 -08005926 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
5927 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305928 devices, flags, &out->stream);
5929
5930
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005931 if (!out) {
5932 return -ENOMEM;
5933 }
5934
Haynes Mathew George204045b2015-02-25 20:32:03 -08005935 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005936 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305937 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08005938 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08005939 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5940
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005941 if (devices == AUDIO_DEVICE_NONE)
5942 devices = AUDIO_DEVICE_OUT_SPEAKER;
5943
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005944 out->flags = flags;
5945 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07005946 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07005947 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005948 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05305949 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05305950 if (out->channel_mask == AUDIO_CHANNEL_NONE)
5951 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
5952 else
5953 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07005954 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005955 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08005956 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305957 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305958 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305959 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005960 out->hal_output_suspend_supported = 0;
5961 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05305962 out->set_dual_mono = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005963
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05305964 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05305965 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07005966 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
5967
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005968 if (audio_is_linear_pcm(out->format) &&
5969 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
5970 pthread_mutex_lock(&adev->lock);
5971 if (is_hdmi) {
5972 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
5973 ret = read_hdmi_sink_caps(out);
5974 } else if (is_usb_dev) {
5975 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
5976 &config->format,
5977 &out->supported_formats[0],
5978 MAX_SUPPORTED_FORMATS,
5979 &config->channel_mask,
5980 &out->supported_channel_masks[0],
5981 MAX_SUPPORTED_CHANNEL_MASKS,
5982 &config->sample_rate,
5983 &out->supported_sample_rates[0],
5984 MAX_SUPPORTED_SAMPLE_RATES);
5985 ALOGV("plugged dev USB ret %d", ret);
5986 } else {
5987 ret = -1;
5988 }
5989 pthread_mutex_unlock(&adev->lock);
5990 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005991 if (ret == -ENOSYS) {
5992 /* ignore and go with default */
5993 ret = 0;
5994 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005995 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08005996 goto error_open;
5997 }
5998 }
5999 }
6000
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006001 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07006002#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006003 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6004 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6005 out->sample_rate == 32000 || out->sample_rate == 48000)) {
6006 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
6007 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
6008 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
6009
6010 out->config = default_pcm_config_voip_copp;
6011 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6012 out->config.rate = out->sample_rate;
6013
6014#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05306015 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006016 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08006017 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006018 ret = voice_extn_compress_voip_open_output_stream(out);
6019 if (ret != 0) {
6020 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6021 __func__, ret);
6022 goto error_open;
6023 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006024#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006025 } else if (audio_is_linear_pcm(out->format) &&
6026 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6027 out->channel_mask = config->channel_mask;
6028 out->sample_rate = config->sample_rate;
6029 out->format = config->format;
6030 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6031 // does this change?
6032 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6033 out->config.rate = config->sample_rate;
6034 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6035 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6036 audio_bytes_per_sample(config->format));
6037 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006038 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306039 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306040 pthread_mutex_lock(&adev->lock);
6041 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6042 pthread_mutex_unlock(&adev->lock);
6043
6044 // reject offload during card offline to allow
6045 // fallback to s/w paths
6046 if (offline) {
6047 ret = -ENODEV;
6048 goto error_open;
6049 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006050
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006051 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6052 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6053 ALOGE("%s: Unsupported Offload information", __func__);
6054 ret = -EINVAL;
6055 goto error_open;
6056 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006057
Atul Khare3fa6e542017-08-09 00:56:17 +05306058 if (config->offload_info.format == 0)
6059 config->offload_info.format = config->format;
6060 if (config->offload_info.sample_rate == 0)
6061 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006062
Mingming Yin90310102013-11-13 16:57:00 -08006063 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306064 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006065 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006066 ret = -EINVAL;
6067 goto error_open;
6068 }
6069
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006070 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6071 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6072 (audio_extn_passthru_is_passthrough_stream(out)) &&
6073 !((config->sample_rate == 48000) ||
6074 (config->sample_rate == 96000) ||
6075 (config->sample_rate == 192000))) {
6076 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6077 __func__, config->sample_rate, config->offload_info.format);
6078 ret = -EINVAL;
6079 goto error_open;
6080 }
6081
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006082 out->compr_config.codec = (struct snd_codec *)
6083 calloc(1, sizeof(struct snd_codec));
6084
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006085 if (!out->compr_config.codec) {
6086 ret = -ENOMEM;
6087 goto error_open;
6088 }
6089
Dhananjay Kumarac341582017-02-23 23:42:25 +05306090 out->stream.pause = out_pause;
6091 out->stream.resume = out_resume;
6092 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306093 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306094 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006095 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306096 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006097 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306098 } else {
6099 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6100 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006101 }
vivek mehta446c3962015-09-14 10:57:35 -07006102
6103 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006104 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6105 config->format == 0 && config->sample_rate == 0 &&
6106 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006107 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006108 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6109 } else {
6110 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6111 ret = -EEXIST;
6112 goto error_open;
6113 }
vivek mehta446c3962015-09-14 10:57:35 -07006114 }
6115
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006116 if (config->offload_info.channel_mask)
6117 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006118 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006119 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006120 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006121 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306122 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006123 ret = -EINVAL;
6124 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006125 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006126
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006127 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006128 out->sample_rate = config->offload_info.sample_rate;
6129
Mingming Yin3ee55c62014-08-04 14:23:35 -07006130 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006131
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306132 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306133 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306134 audio_extn_dolby_send_ddp_endp_params(adev);
6135 audio_extn_dolby_set_dmid(adev);
6136 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006137
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006138 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006139 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006140 out->compr_config.codec->bit_rate =
6141 config->offload_info.bit_rate;
6142 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306143 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006144 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306145 /* Update bit width only for non passthrough usecases.
6146 * For passthrough usecases, the output will always be opened @16 bit
6147 */
6148 if (!audio_extn_passthru_is_passthrough_stream(out))
6149 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306150
6151 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6152 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6153 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6154
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006155 /*TODO: Do we need to change it for passthrough */
6156 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006157
Manish Dewangana6fc5442015-08-24 20:30:31 +05306158 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6159 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306160 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306161 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306162 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6163 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306164
6165 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6166 AUDIO_FORMAT_PCM) {
6167
6168 /*Based on platform support, configure appropriate alsa format for corresponding
6169 *hal input format.
6170 */
6171 out->compr_config.codec->format = hal_format_to_alsa(
6172 config->offload_info.format);
6173
Ashish Jain83a6cc22016-06-28 14:34:17 +05306174 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306175 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306176 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306177
Dhananjay Kumarac341582017-02-23 23:42:25 +05306178 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306179 *hal input format and alsa format might differ based on platform support.
6180 */
6181 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306182 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306183
6184 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6185
6186 /* Check if alsa session is configured with the same format as HAL input format,
6187 * if not then derive correct fragment size needed to accomodate the
6188 * conversion of HAL input format to alsa format.
6189 */
6190 audio_extn_utils_update_direct_pcm_fragment_size(out);
6191
6192 /*if hal input and output fragment size is different this indicates HAL input format is
6193 *not same as the alsa format
6194 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306195 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306196 /*Allocate a buffer to convert input data to the alsa configured format.
6197 *size of convert buffer is equal to the size required to hold one fragment size
6198 *worth of pcm data, this is because flinger does not write more than fragment_size
6199 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306200 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6201 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306202 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6203 ret = -ENOMEM;
6204 goto error_open;
6205 }
6206 }
6207 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6208 out->compr_config.fragment_size =
6209 audio_extn_passthru_get_buffer_size(&config->offload_info);
6210 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6211 } else {
6212 out->compr_config.fragment_size =
6213 platform_get_compress_offload_buffer_size(&config->offload_info);
6214 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6215 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006216
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306217 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6218 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6219 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006220 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306221 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006222
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306223 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6224 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6225 }
6226
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006227 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6228 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006229
Manish Dewangan69426c82017-01-30 17:35:36 +05306230 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6231 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6232 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6233 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6234 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6235 } else {
6236 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6237 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006238
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306239 memset(&out->channel_map_param, 0,
6240 sizeof(struct audio_out_channel_map_param));
6241
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006242 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306243 out->send_next_track_params = false;
6244 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006245 out->offload_state = OFFLOAD_STATE_IDLE;
6246 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006247 out->writeAt.tv_sec = 0;
6248 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006249
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006250 audio_extn_dts_create_state_notifier_node(out->usecase);
6251
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006252 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6253 __func__, config->offload_info.version,
6254 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306255
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306256 /* Check if DSD audio format is supported in codec
6257 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306258 */
6259
6260 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306261 (!platform_check_codec_dsd_support(adev->platform) ||
6262 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306263 ret = -EINVAL;
6264 goto error_open;
6265 }
6266
Ashish Jain5106d362016-05-11 19:23:33 +05306267 /* Disable gapless if any of the following is true
6268 * passthrough playback
6269 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306270 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306271 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306272 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306273 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006274 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306275 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306276 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306277 check_and_set_gapless_mode(adev, false);
6278 } else
6279 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006280
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306281 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006282 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6283 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306284 if (config->format == AUDIO_FORMAT_DSD) {
6285 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6286 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6287 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006288
6289 create_offload_callback_thread(out);
6290
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006291 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006292 switch (config->sample_rate) {
6293 case 0:
6294 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6295 break;
6296 case 8000:
6297 case 16000:
6298 case 48000:
6299 out->sample_rate = config->sample_rate;
6300 break;
6301 default:
6302 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
6303 config->sample_rate);
6304 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6305 ret = -EINVAL;
6306 goto error_open;
6307 }
6308 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6309 switch (config->channel_mask) {
6310 case AUDIO_CHANNEL_NONE:
6311 case AUDIO_CHANNEL_OUT_STEREO:
6312 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6313 break;
6314 default:
6315 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
6316 config->channel_mask);
6317 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6318 ret = -EINVAL;
6319 goto error_open;
6320 }
6321 switch (config->format) {
6322 case AUDIO_FORMAT_DEFAULT:
6323 case AUDIO_FORMAT_PCM_16_BIT:
6324 out->format = AUDIO_FORMAT_PCM_16_BIT;
6325 break;
6326 default:
6327 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
6328 config->format);
6329 config->format = AUDIO_FORMAT_PCM_16_BIT;
6330 ret = -EINVAL;
6331 goto error_open;
6332 }
6333
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306334 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006335 if (ret != 0) {
6336 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006337 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006338 goto error_open;
6339 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006340 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006341 if (config->sample_rate == 0)
6342 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6343 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6344 config->sample_rate != 8000) {
6345 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6346 ret = -EINVAL;
6347 goto error_open;
6348 }
6349 out->sample_rate = config->sample_rate;
6350 out->config.rate = config->sample_rate;
6351 if (config->format == AUDIO_FORMAT_DEFAULT)
6352 config->format = AUDIO_FORMAT_PCM_16_BIT;
6353 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6354 config->format = AUDIO_FORMAT_PCM_16_BIT;
6355 ret = -EINVAL;
6356 goto error_open;
6357 }
6358 out->format = config->format;
6359 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
6360 out->config = pcm_config_afe_proxy_playback;
6361 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006362 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05306363 unsigned int channels = 0;
6364 /*Update config params to default if not set by the caller*/
6365 if (config->sample_rate == 0)
6366 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6367 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6368 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6369 if (config->format == AUDIO_FORMAT_DEFAULT)
6370 config->format = AUDIO_FORMAT_PCM_16_BIT;
6371
6372 channels = audio_channel_count_from_out_mask(out->channel_mask);
6373
Varun Balaraje49253e2017-07-06 19:48:56 +05306374 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6375 out->usecase = get_interactive_usecase(adev);
6376 out->config = pcm_config_low_latency;
6377 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306378 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006379 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6380 out->flags);
6381 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006382 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6383 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6384 out->config = pcm_config_mmap_playback;
6385 out->stream.start = out_start;
6386 out->stream.stop = out_stop;
6387 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6388 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306389 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6390 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006391 out->hal_output_suspend_supported =
6392 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6393 out->dynamic_pm_qos_config_supported =
6394 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6395 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006396 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6397 } else {
6398 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6399 //the mixer path will be a string similar to "low-latency-playback resume"
6400 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6401 strlcat(out->pm_qos_mixer_path,
6402 " resume", MAX_MIXER_PATH_LEN);
6403 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6404 out->pm_qos_mixer_path);
6405 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306406 out->config = pcm_config_low_latency;
6407 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6408 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6409 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306410 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6411 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6412 if (out->config.period_size <= 0) {
6413 ALOGE("Invalid configuration period size is not valid");
6414 ret = -EINVAL;
6415 goto error_open;
6416 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306417 } else {
6418 /* primary path is the default path selected if no other outputs are available/suitable */
6419 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6420 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6421 }
6422 out->hal_ip_format = format = out->format;
6423 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6424 out->hal_op_format = pcm_format_to_hal(out->config.format);
6425 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6426 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006427 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306428 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306429 if (out->hal_ip_format != out->hal_op_format) {
6430 uint32_t buffer_size = out->config.period_size *
6431 format_to_bitwidth_table[out->hal_op_format] *
6432 out->config.channels;
6433 out->convert_buffer = calloc(1, buffer_size);
6434 if (out->convert_buffer == NULL){
6435 ALOGE("Allocation failed for convert buffer for size %d",
6436 out->compr_config.fragment_size);
6437 ret = -ENOMEM;
6438 goto error_open;
6439 }
6440 ALOGD("Convert buffer allocated of size %d", buffer_size);
6441 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006442 }
6443
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006444 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6445 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306446
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006447 /* TODO remove this hardcoding and check why width is zero*/
6448 if (out->bit_width == 0)
6449 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306450 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006451 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006452 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306453 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306454 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006455 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6456 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6457 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006458 if(adev->primary_output == NULL)
6459 adev->primary_output = out;
6460 else {
6461 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006462 ret = -EEXIST;
6463 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006464 }
6465 }
6466
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006467 /* Check if this usecase is already existing */
6468 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006469 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6470 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006471 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006472 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006473 ret = -EEXIST;
6474 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006475 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006477 pthread_mutex_unlock(&adev->lock);
6478
6479 out->stream.common.get_sample_rate = out_get_sample_rate;
6480 out->stream.common.set_sample_rate = out_set_sample_rate;
6481 out->stream.common.get_buffer_size = out_get_buffer_size;
6482 out->stream.common.get_channels = out_get_channels;
6483 out->stream.common.get_format = out_get_format;
6484 out->stream.common.set_format = out_set_format;
6485 out->stream.common.standby = out_standby;
6486 out->stream.common.dump = out_dump;
6487 out->stream.common.set_parameters = out_set_parameters;
6488 out->stream.common.get_parameters = out_get_parameters;
6489 out->stream.common.add_audio_effect = out_add_audio_effect;
6490 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6491 out->stream.get_latency = out_get_latency;
6492 out->stream.set_volume = out_set_volume;
6493 out->stream.write = out_write;
6494 out->stream.get_render_position = out_get_render_position;
6495 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006496 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006497
Haynes Mathew George16081042017-05-31 17:16:49 -07006498 if (out->realtime)
6499 out->af_period_multiplier = af_period_multiplier;
6500 else
6501 out->af_period_multiplier = 1;
6502
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006503 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006504 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006505 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006506
6507 config->format = out->stream.common.get_format(&out->stream.common);
6508 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6509 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05306510 register_format(out->format, out->supported_formats);
6511 register_channel_mask(out->channel_mask, out->supported_channel_masks);
6512 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006513
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306514 /*
6515 By locking output stream before registering, we allow the callback
6516 to update stream's state only after stream's initial state is set to
6517 adev state.
6518 */
6519 lock_output_stream(out);
6520 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6521 pthread_mutex_lock(&adev->lock);
6522 out->card_status = adev->card_status;
6523 pthread_mutex_unlock(&adev->lock);
6524 pthread_mutex_unlock(&out->lock);
6525
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006526 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306527 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006528 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006529
6530 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6531 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6532 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006533 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306534 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006535 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006536 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306537 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006538 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6539 out->usecase, PCM_PLAYBACK);
6540 hdlr_stream_cfg.flags = out->flags;
6541 hdlr_stream_cfg.type = PCM_PLAYBACK;
6542 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6543 &hdlr_stream_cfg);
6544 if (ret) {
6545 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6546 out->adsp_hdlr_stream_handle = NULL;
6547 }
6548 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306549 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006550 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006551 if (ret < 0) {
6552 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6553 out->ip_hdlr_handle = NULL;
6554 }
6555 }
Eric Laurent994a6932013-07-17 11:51:42 -07006556 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006557 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006558
6559error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306560 if (out->convert_buffer)
6561 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006562 free(out);
6563 *stream_out = NULL;
6564 ALOGD("%s: exit: ret %d", __func__, ret);
6565 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006566}
6567
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306568void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006569 struct audio_stream_out *stream)
6570{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006571 struct stream_out *out = (struct stream_out *)stream;
6572 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006573 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006574
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006575 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306576
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306577 // must deregister from sndmonitor first to prevent races
6578 // between the callback and close_stream
6579 audio_extn_snd_mon_unregister_listener(out);
6580
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006581 /* close adsp hdrl session before standby */
6582 if (out->adsp_hdlr_stream_handle) {
6583 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6584 if (ret)
6585 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6586 out->adsp_hdlr_stream_handle = NULL;
6587 }
6588
Manish Dewangan21a850a2017-08-14 12:03:55 +05306589 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006590 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6591 out->ip_hdlr_handle = NULL;
6592 }
6593
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006594 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306595 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006596 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306597 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306598 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006599 if(ret != 0)
6600 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6601 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006602 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006603 out_standby(&stream->common);
6604
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006605 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006606 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006607 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006608 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006609 if (out->compr_config.codec != NULL)
6610 free(out->compr_config.codec);
6611 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006612
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306613 out->a2dp_compress_mute = false;
6614
Varun Balaraje49253e2017-07-06 19:48:56 +05306615 if (is_interactive_usecase(out->usecase))
6616 free_interactive_usecase(adev, out->usecase);
6617
Ashish Jain83a6cc22016-06-28 14:34:17 +05306618 if (out->convert_buffer != NULL) {
6619 free(out->convert_buffer);
6620 out->convert_buffer = NULL;
6621 }
6622
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006623 if (adev->voice_tx_output == out)
6624 adev->voice_tx_output = NULL;
6625
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306626 if (adev->primary_output == out)
6627 adev->primary_output = NULL;
6628
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006629 pthread_cond_destroy(&out->cond);
6630 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006631 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006632 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006633}
6634
6635static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6636{
6637 struct audio_device *adev = (struct audio_device *)dev;
6638 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006639 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006640 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006641 int ret;
6642 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006643
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006644 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006645 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006646
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306647 if (!parms)
6648 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306649
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306650 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6651 if (ret >= 0) {
6652 /* When set to false, HAL should disable EC and NS */
6653 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6654 adev->bt_sco_on = true;
6655 else
6656 adev->bt_sco_on = false;
6657 }
6658
Naresh Tanniru4c630392014-05-12 01:05:52 +05306659 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006660 status = voice_set_parameters(adev, parms);
6661 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006662 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006663
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006664 status = platform_set_parameters(adev->platform, parms);
6665 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006666 goto done;
6667
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006668 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6669 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006670 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006671 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6672 adev->bluetooth_nrec = true;
6673 else
6674 adev->bluetooth_nrec = false;
6675 }
6676
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006677 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6678 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006679 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6680 adev->screen_off = false;
6681 else
6682 adev->screen_off = true;
6683 }
6684
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006685 ret = str_parms_get_int(parms, "rotation", &val);
6686 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006687 bool reverse_speakers = false;
6688 switch(val) {
6689 // FIXME: note that the code below assumes that the speakers are in the correct placement
6690 // relative to the user when the device is rotated 90deg from its default rotation. This
6691 // assumption is device-specific, not platform-specific like this code.
6692 case 270:
6693 reverse_speakers = true;
6694 break;
6695 case 0:
6696 case 90:
6697 case 180:
6698 break;
6699 default:
6700 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006701 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006702 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006703 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006704 // check and set swap
6705 // - check if orientation changed and speaker active
6706 // - set rotation and cache the rotation value
6707 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006708 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006709 }
6710
Mingming Yin514a8bc2014-07-29 15:22:21 -07006711 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6712 if (ret >= 0) {
6713 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6714 adev->bt_wb_speech_enabled = true;
6715 else
6716 adev->bt_wb_speech_enabled = false;
6717 }
6718
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006719 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6720 if (ret >= 0) {
6721 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306722 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08006723 if (audio_is_output_device(val) &&
6724 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006725 ALOGV("cache new ext disp type and edid");
6726 ret = platform_get_ext_disp_type(adev->platform);
6727 if (ret < 0) {
6728 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05306729 } else {
6730 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006731 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306732 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07006733 /*
6734 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6735 * Per AudioPolicyManager, USB device is higher priority than WFD.
6736 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6737 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6738 * starting voice call on USB
6739 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006740 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306741 if (ret >= 0)
6742 audio_extn_usb_add_device(device, atoi(value));
6743
Zhou Song6f862822017-11-06 17:27:57 +08006744 if (!audio_extn_usb_is_tunnel_supported()) {
6745 ALOGV("detected USB connect .. disable proxy");
6746 adev->allow_afe_proxy_usage = false;
6747 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006748 }
6749 }
6750
6751 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6752 if (ret >= 0) {
6753 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306754 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07006755 /*
6756 * The HDMI / Displayport disconnect handling has been moved to
6757 * audio extension to ensure that its parameters are not
6758 * invalidated prior to updating sysfs of the disconnect event
6759 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6760 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306761 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006762 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306763 if (ret >= 0)
6764 audio_extn_usb_remove_device(device, atoi(value));
6765
Zhou Song6f862822017-11-06 17:27:57 +08006766 if (!audio_extn_usb_is_tunnel_supported()) {
6767 ALOGV("detected USB disconnect .. enable proxy");
6768 adev->allow_afe_proxy_usage = true;
6769 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006770 }
6771 }
6772
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306773 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6774 if (ret >= 0) {
6775 struct audio_usecase *usecase;
6776 struct listnode *node;
6777 list_for_each(node, &adev->usecase_list) {
6778 usecase = node_to_item(node, struct audio_usecase, list);
6779 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07006780 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306781 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08006782
6783 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306784 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08006785 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306786 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306787 //force device switch to re configure encoder
6788 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306789 audio_extn_a2dp_set_handoff_mode(false);
6790 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306791 break;
6792 }
6793 }
6794 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006795
6796 //handle vr audio setparam
6797 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6798 value, sizeof(value));
6799 if (ret >= 0) {
6800 ALOGI("Setting vr mode to be %s", value);
6801 if (!strncmp(value, "true", 4)) {
6802 adev->vr_audio_mode_enabled = true;
6803 ALOGI("Setting vr mode to true");
6804 } else if (!strncmp(value, "false", 5)) {
6805 adev->vr_audio_mode_enabled = false;
6806 ALOGI("Setting vr mode to false");
6807 } else {
6808 ALOGI("wrong vr mode set");
6809 }
6810 }
6811
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306812 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006813done:
6814 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006815 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306816error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006817 ALOGV("%s: exit with code(%d)", __func__, status);
6818 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006819}
6820
6821static char* adev_get_parameters(const struct audio_hw_device *dev,
6822 const char *keys)
6823{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006824 struct audio_device *adev = (struct audio_device *)dev;
6825 struct str_parms *reply = str_parms_create();
6826 struct str_parms *query = str_parms_create_str(keys);
6827 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05306828 char value[256] = {0};
6829 int ret = 0;
6830
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006831 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006832 if (reply) {
6833 str_parms_destroy(reply);
6834 }
6835 if (query) {
6836 str_parms_destroy(query);
6837 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006838 ALOGE("adev_get_parameters: failed to create query or reply");
6839 return NULL;
6840 }
6841
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006842 //handle vr audio getparam
6843
6844 ret = str_parms_get_str(query,
6845 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6846 value, sizeof(value));
6847
6848 if (ret >= 0) {
6849 bool vr_audio_enabled = false;
6850 pthread_mutex_lock(&adev->lock);
6851 vr_audio_enabled = adev->vr_audio_mode_enabled;
6852 pthread_mutex_unlock(&adev->lock);
6853
6854 ALOGI("getting vr mode to %d", vr_audio_enabled);
6855
6856 if (vr_audio_enabled) {
6857 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6858 "true");
6859 goto exit;
6860 } else {
6861 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6862 "false");
6863 goto exit;
6864 }
6865 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006866
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006867 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006868 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08006869 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006870 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05306871 pthread_mutex_unlock(&adev->lock);
6872
Naresh Tannirud7205b62014-06-20 02:54:48 +05306873exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006874 str = str_parms_to_str(reply);
6875 str_parms_destroy(query);
6876 str_parms_destroy(reply);
6877
6878 ALOGV("%s: exit: returns - %s", __func__, str);
6879 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006880}
6881
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006882static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006883{
6884 return 0;
6885}
6886
6887static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
6888{
Haynes Mathew George5191a852013-09-11 14:19:36 -07006889 int ret;
6890 struct audio_device *adev = (struct audio_device *)dev;
6891 pthread_mutex_lock(&adev->lock);
6892 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07006893 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07006894 pthread_mutex_unlock(&adev->lock);
6895 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006896}
6897
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006898static int adev_set_master_volume(struct audio_hw_device *dev __unused,
6899 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006900{
6901 return -ENOSYS;
6902}
6903
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006904static int adev_get_master_volume(struct audio_hw_device *dev __unused,
6905 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006906{
6907 return -ENOSYS;
6908}
6909
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006910static int adev_set_master_mute(struct audio_hw_device *dev __unused,
6911 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006912{
6913 return -ENOSYS;
6914}
6915
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006916static int adev_get_master_mute(struct audio_hw_device *dev __unused,
6917 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006918{
6919 return -ENOSYS;
6920}
6921
6922static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
6923{
6924 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07006925 struct listnode *node;
6926 struct audio_usecase *usecase = NULL;
6927 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006928 pthread_mutex_lock(&adev->lock);
6929 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006930 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006931 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08006932 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07006933 list_for_each(node, &adev->usecase_list) {
6934 usecase = node_to_item(node, struct audio_usecase, list);
6935 if (usecase->type == VOICE_CALL)
6936 break;
6937 }
6938 if (usecase &&
6939 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
6940 ret = audio_extn_usb_check_and_set_svc_int(usecase,
6941 true);
6942 if (ret != 0) {
6943 /* default service interval was successfully updated,
6944 reopen USB backend with new service interval */
6945 check_usecases_codec_backend(adev,
6946 usecase,
6947 usecase->out_snd_device);
6948 }
6949 }
6950
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006951 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07006952 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006953 adev->current_call_output = NULL;
6954 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006955 }
6956 pthread_mutex_unlock(&adev->lock);
6957 return 0;
6958}
6959
6960static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
6961{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006962 int ret;
6963
6964 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08006965 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006966 ret = voice_set_mic_mute((struct audio_device *)dev, state);
6967 pthread_mutex_unlock(&adev->lock);
6968
6969 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006970}
6971
6972static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
6973{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006974 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006975 return 0;
6976}
6977
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006978static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006979 const struct audio_config *config)
6980{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006981 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006982
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006983 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
6984 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006985}
6986
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006987static bool adev_input_allow_hifi_record(struct audio_device *adev,
6988 audio_devices_t devices,
6989 audio_input_flags_t flags,
6990 audio_source_t source) {
6991 const bool allowed = true;
6992
6993 if (!audio_is_usb_in_device(devices))
6994 return !allowed;
6995
6996 switch (flags) {
6997 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006998 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07006999 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7000 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007001 default:
7002 return !allowed;
7003 }
7004
7005 switch (source) {
7006 case AUDIO_SOURCE_DEFAULT:
7007 case AUDIO_SOURCE_MIC:
7008 case AUDIO_SOURCE_UNPROCESSED:
7009 break;
7010 default:
7011 return !allowed;
7012 }
7013
7014 switch (adev->mode) {
7015 case 0:
7016 break;
7017 default:
7018 return !allowed;
7019 }
7020
7021 return allowed;
7022}
7023
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007024static int adev_update_voice_comm_input_stream(struct stream_in *in,
7025 struct audio_config *config)
7026{
7027 bool valid_rate = (config->sample_rate == 8000 ||
7028 config->sample_rate == 16000 ||
7029 config->sample_rate == 32000 ||
7030 config->sample_rate == 48000);
7031 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
7032
7033#ifndef COMPRESS_VOIP_ENABLED
kunleizd96526c2018-04-09 11:12:32 +08007034 if (valid_rate && valid_ch &&
7035 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007036 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7037 in->config = default_pcm_config_voip_copp;
7038 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
7039 DEFAULT_VOIP_BUF_DURATION_MS,
7040 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
7041 } else {
kunleizbdd9ad02018-04-24 10:53:17 +08007042 ALOGW("%s No valid input in voip, use defaults"
7043 "sample rate %u, channel mask 0x%X",
7044 __func__, config->sample_rate, in->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007045 }
7046 in->config.rate = config->sample_rate;
7047 in->sample_rate = config->sample_rate;
7048#else
7049 //XXX needed for voice_extn_compress_voip_open_input_stream
7050 in->config.rate = config->sample_rate;
7051 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7052 voice_extn_compress_voip_is_active(in->dev)) &&
7053 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7054 valid_rate && valid_ch) {
7055 voice_extn_compress_voip_open_input_stream(in);
7056 // update rate entries to match config from AF
7057 in->config.rate = config->sample_rate;
7058 in->sample_rate = config->sample_rate;
7059 } else {
7060 ALOGW("%s compress voip not active, use defaults", __func__);
7061 }
7062#endif
7063 return 0;
7064}
7065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007066static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007067 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007068 audio_devices_t devices,
7069 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007070 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307071 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007072 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007073 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007074{
7075 struct audio_device *adev = (struct audio_device *)dev;
7076 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007077 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007078 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007079 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05307080 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007081 bool is_usb_dev = audio_is_usb_in_device(devices);
7082 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
7083 devices,
7084 flags,
7085 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307086
kunleizdff872d2018-08-20 14:40:33 +08007087 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007088 is_usb_dev = false;
7089 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
7090 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
7091 __func__, devices);
7092 }
7093
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007094 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007095
7096 if (!(is_usb_dev && may_use_hifi_record)) {
7097 if (config->sample_rate == 0)
7098 config->sample_rate = 48000;
7099 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7100 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7101 if (config->format == AUDIO_FORMAT_DEFAULT)
7102 config->format = AUDIO_FORMAT_PCM_16_BIT;
7103
7104 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
7105
7106 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
7107 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05307108 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007109
7110 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007111
7112 if (!in) {
7113 ALOGE("failed to allocate input stream");
7114 return -ENOMEM;
7115 }
7116
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307117 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307118 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7119 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007120 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007121 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007123 in->stream.common.get_sample_rate = in_get_sample_rate;
7124 in->stream.common.set_sample_rate = in_set_sample_rate;
7125 in->stream.common.get_buffer_size = in_get_buffer_size;
7126 in->stream.common.get_channels = in_get_channels;
7127 in->stream.common.get_format = in_get_format;
7128 in->stream.common.set_format = in_set_format;
7129 in->stream.common.standby = in_standby;
7130 in->stream.common.dump = in_dump;
7131 in->stream.common.set_parameters = in_set_parameters;
7132 in->stream.common.get_parameters = in_get_parameters;
7133 in->stream.common.add_audio_effect = in_add_audio_effect;
7134 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7135 in->stream.set_gain = in_set_gain;
7136 in->stream.read = in_read;
7137 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307138 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007139
7140 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007141 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007142 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007143 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007144 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007145 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007146 in->bit_width = 16;
7147 in->af_period_multiplier = 1;
7148
7149 /* Update config params with the requested sample rate and channels */
7150 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
7151 (adev->mode != AUDIO_MODE_IN_CALL)) {
7152 ret = -EINVAL;
7153 goto err_open;
7154 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007155
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007156 if (is_usb_dev && may_use_hifi_record) {
7157 /* HiFi record selects an appropriate format, channel, rate combo
7158 depending on sink capabilities*/
7159 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7160 &config->format,
7161 &in->supported_formats[0],
7162 MAX_SUPPORTED_FORMATS,
7163 &config->channel_mask,
7164 &in->supported_channel_masks[0],
7165 MAX_SUPPORTED_CHANNEL_MASKS,
7166 &config->sample_rate,
7167 &in->supported_sample_rates[0],
7168 MAX_SUPPORTED_SAMPLE_RATES);
7169 if (ret != 0) {
7170 ret = -EINVAL;
7171 goto err_open;
7172 }
7173 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007174 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307175 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05307176 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
7177 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
7178 in->config.format = PCM_FORMAT_S32_LE;
7179 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307180 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
7181 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
7182 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
7183 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7184 bool ret_error = false;
7185 in->bit_width = 24;
7186 /* 24 bit is restricted to UNPROCESSED source only,also format supported
7187 from HAL is 24_packed and 8_24
7188 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
7189 24_packed return error indicating supported format is 24_packed
7190 *> In case of any other source requesting 24 bit or float return error
7191 indicating format supported is 16 bit only.
7192
7193 on error flinger will retry with supported format passed
7194 */
7195 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
7196 (source != AUDIO_SOURCE_CAMCORDER)) {
7197 config->format = AUDIO_FORMAT_PCM_16_BIT;
7198 if (config->sample_rate > 48000)
7199 config->sample_rate = 48000;
7200 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07007201 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
7202 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307203 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
7204 ret_error = true;
7205 }
7206
7207 if (ret_error) {
7208 ret = -EINVAL;
7209 goto err_open;
7210 }
7211 }
7212
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007213 in->channel_mask = config->channel_mask;
7214 in->format = config->format;
7215
7216 in->usecase = USECASE_AUDIO_RECORD;
7217 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
7218 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
7219 is_low_latency = true;
7220#if LOW_LATENCY_CAPTURE_USE_CASE
7221 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
7222#endif
7223 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
7224 }
7225
7226 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
7227 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
7228 in->realtime = 0;
7229 in->usecase = USECASE_AUDIO_RECORD_MMAP;
7230 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07007231 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007232 in->stream.start = in_start;
7233 in->stream.stop = in_stop;
7234 in->stream.create_mmap_buffer = in_create_mmap_buffer;
7235 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007236 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007237 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
7238 } else if (in->realtime) {
7239 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07007240 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007241 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007242 in->sample_rate = in->config.rate;
7243 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07007244 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007245 in->usecase = USECASE_AUDIO_RECORD_HIFI;
7246 in->config = pcm_config_audio_capture;
7247 frame_size = audio_stream_in_frame_size(&in->stream);
7248 buffer_size = get_input_buffer_size(config->sample_rate,
7249 config->format,
7250 channel_count,
7251 false /*is_low_latency*/);
7252 in->config.period_size = buffer_size / frame_size;
7253 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007254 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07007255 switch (config->format) {
7256 case AUDIO_FORMAT_PCM_32_BIT:
7257 in->bit_width = 32;
7258 break;
7259 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
7260 case AUDIO_FORMAT_PCM_8_24_BIT:
7261 in->bit_width = 24;
7262 break;
7263 default:
7264 in->bit_width = 16;
7265 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007266 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007267 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007268 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05307269 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007270 if (config->sample_rate == 0)
7271 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7272 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
7273 config->sample_rate != 8000) {
7274 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7275 ret = -EINVAL;
7276 goto err_open;
7277 }
7278 if (config->format == AUDIO_FORMAT_DEFAULT)
7279 config->format = AUDIO_FORMAT_PCM_16_BIT;
7280 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
7281 config->format = AUDIO_FORMAT_PCM_16_BIT;
7282 ret = -EINVAL;
7283 goto err_open;
7284 }
7285
7286 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
7287 in->config = pcm_config_afe_proxy_record;
7288 in->config.channels = channel_count;
7289 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307290 in->sample_rate = config->sample_rate;
Haynes Mathew George46740472017-10-27 18:40:12 -07007291 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05307292 int ret_val;
7293 pthread_mutex_lock(&adev->lock);
7294 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
7295 in, config, &channel_mask_updated);
7296 pthread_mutex_unlock(&adev->lock);
7297
7298 if (!ret_val) {
7299 if (channel_mask_updated == true) {
7300 ALOGD("%s: return error to retry with updated channel mask (%#x)",
7301 __func__, config->channel_mask);
7302 ret = -EINVAL;
7303 goto err_open;
7304 }
7305 ALOGD("%s: created multi-channel session succesfully",__func__);
7306 } else if (audio_extn_compr_cap_enabled() &&
7307 audio_extn_compr_cap_format_supported(config->format) &&
7308 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
7309 audio_extn_compr_cap_init(in);
7310 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05307311 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05307312 ret = audio_extn_cin_configure_input_stream(in);
7313 if (ret)
7314 goto err_open;
7315 } else {
7316 in->config = pcm_config_audio_capture;
7317 in->config.rate = config->sample_rate;
7318 in->config.format = pcm_format_from_audio_format(config->format);
7319 in->config.channels = channel_count;
7320 in->sample_rate = config->sample_rate;
7321 in->format = config->format;
7322 frame_size = audio_stream_in_frame_size(&in->stream);
7323 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07007324 config->format,
7325 channel_count,
7326 is_low_latency);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307327 in->config.period_size = buffer_size / frame_size;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007328
Revathi Uddarajud2634032017-12-07 14:42:34 +05307329 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
7330 /* optionally use VOIP usecase depending on config(s) */
7331 ret = adev_update_voice_comm_input_stream(in, config);
7332 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007333
Revathi Uddarajud2634032017-12-07 14:42:34 +05307334 if (ret) {
7335 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
7336 goto err_open;
7337 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007338 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007339 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307340 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7341 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007342 devices, flags, in->format,
7343 in->sample_rate, in->bit_width,
7344 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307345 register_format(in->format, in->supported_formats);
7346 register_channel_mask(in->channel_mask, in->supported_channel_masks);
7347 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307348
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007349 /* This stream could be for sound trigger lab,
7350 get sound trigger pcm if present */
7351 audio_extn_sound_trigger_check_and_get_session(in);
7352
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307353 lock_input_stream(in);
7354 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
7355 pthread_mutex_lock(&adev->lock);
7356 in->card_status = adev->card_status;
7357 pthread_mutex_unlock(&adev->lock);
7358 pthread_mutex_unlock(&in->lock);
7359
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007360 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07007361 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007362 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007363
7364err_open:
7365 free(in);
7366 *stream_in = NULL;
7367 return ret;
7368}
7369
7370static void adev_close_input_stream(struct audio_hw_device *dev,
7371 struct audio_stream_in *stream)
7372{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007373 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007374 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007375 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307376
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307377 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007378
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307379 // must deregister from sndmonitor first to prevent races
7380 // between the callback and close_stream
7381 audio_extn_snd_mon_unregister_listener(stream);
7382
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307383 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07007384 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307385
Pallavid7c7a272018-01-16 11:22:55 +05307386 if (in == NULL) {
7387 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
7388 return;
7389 }
7390
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007391 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307392 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007393 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307394 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007395 if (ret != 0)
7396 ALOGE("%s: Compress voip input cannot be closed, error:%d",
7397 __func__, ret);
7398 } else
7399 in_standby(&stream->common);
7400
Revathi Uddarajud2634032017-12-07 14:42:34 +05307401 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07007402 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007403 audio_extn_ssr_deinit();
7404 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007405
Garmond Leunge2433c32017-09-28 21:51:22 -07007406 if (audio_extn_ffv_get_stream() == in) {
7407 audio_extn_ffv_stream_deinit();
7408 }
7409
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307410 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07007411 audio_extn_compr_cap_format_supported(in->config.format))
7412 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05307413
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307414 if (audio_extn_cin_attached_usecase(in->usecase))
7415 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007416
Mingming Yinfd7607b2016-01-22 12:48:44 -08007417 if (in->is_st_session) {
7418 ALOGV("%s: sound trigger pcm stop lab", __func__);
7419 audio_extn_sound_trigger_stop_lab(in);
7420 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007421 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307422 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007423 return;
7424}
7425
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307426int adev_create_audio_patch(struct audio_hw_device *dev,
7427 unsigned int num_sources,
7428 const struct audio_port_config *sources,
7429 unsigned int num_sinks,
7430 const struct audio_port_config *sinks,
7431 audio_patch_handle_t *handle)
7432{
7433
7434
7435 return audio_extn_hw_loopback_create_audio_patch(dev,
7436 num_sources,
7437 sources,
7438 num_sinks,
7439 sinks,
7440 handle);
7441
7442}
7443
7444int adev_release_audio_patch(struct audio_hw_device *dev,
7445 audio_patch_handle_t handle)
7446{
7447 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
7448}
7449
7450int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
7451{
7452 return audio_extn_hw_loopback_get_audio_port(dev, config);
7453}
7454
7455int adev_set_audio_port_config(struct audio_hw_device *dev,
7456 const struct audio_port_config *config)
7457{
7458 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
7459}
7460
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007461static int adev_dump(const audio_hw_device_t *device __unused,
7462 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007463{
7464 return 0;
7465}
7466
7467static int adev_close(hw_device_t *device)
7468{
7469 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07007470
7471 if (!adev)
7472 return 0;
7473
7474 pthread_mutex_lock(&adev_init_lock);
7475
7476 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307477 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007478 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08007479 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307480 audio_extn_utils_release_streams_cfg_lists(
7481 &adev->streams_output_cfg_list,
7482 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307483 if (audio_extn_qaf_is_enabled())
7484 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007485 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007486 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007487 free(adev->snd_dev_ref_cnt);
7488 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007489 if (adev->adm_deinit)
7490 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307491 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007492 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307493 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307494 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007495 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307496 if (adev->device_cfg_params) {
7497 free(adev->device_cfg_params);
7498 adev->device_cfg_params = NULL;
7499 }
Kiran Kandi910e1862013-10-29 13:29:42 -07007500 free(device);
7501 adev = NULL;
7502 }
7503 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007504
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007505 return 0;
7506}
7507
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007508/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
7509 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
7510 * just that it _might_ work.
7511 */
7512static int period_size_is_plausible_for_low_latency(int period_size)
7513{
7514 switch (period_size) {
7515 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07007516 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007517 case 240:
7518 case 320:
7519 case 480:
7520 return 1;
7521 default:
7522 return 0;
7523 }
7524}
7525
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307526static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
7527{
7528 bool is_snd_card_status = false;
7529 bool is_ext_device_status = false;
7530 char value[32];
7531 int card = -1;
7532 card_status_t status;
7533
7534 if (cookie != adev || !parms)
7535 return;
7536
7537 if (!parse_snd_card_status(parms, &card, &status)) {
7538 is_snd_card_status = true;
7539 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
7540 is_ext_device_status = true;
7541 } else {
7542 // not a valid event
7543 return;
7544 }
7545
7546 pthread_mutex_lock(&adev->lock);
7547 if (card == adev->snd_card || is_ext_device_status) {
7548 if (is_snd_card_status && adev->card_status != status) {
7549 adev->card_status = status;
7550 platform_snd_card_update(adev->platform, status);
7551 audio_extn_fm_set_parameters(adev, parms);
7552 } else if (is_ext_device_status) {
7553 platform_set_parameters(adev->platform, parms);
7554 }
7555 }
7556 pthread_mutex_unlock(&adev->lock);
7557 return;
7558}
7559
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307560/* out and adev lock held */
7561static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
7562{
7563 struct audio_usecase *uc_info;
7564 float left_p;
7565 float right_p;
7566 audio_devices_t devices;
7567
7568 uc_info = get_usecase_from_list(adev, out->usecase);
7569 if (uc_info == NULL) {
7570 ALOGE("%s: Could not find the usecase (%d) in the list",
7571 __func__, out->usecase);
7572 return -EINVAL;
7573 }
7574
7575 ALOGD("%s: enter: usecase(%d: %s)", __func__,
7576 out->usecase, use_case_table[out->usecase]);
7577
7578 if (restore) {
7579 // restore A2DP device for active usecases and unmute if required
7580 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
7581 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
7582 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
7583 select_devices(adev, uc_info->id);
7584 pthread_mutex_lock(&out->compr_mute_lock);
7585 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7586 (out->a2dp_compress_mute)) {
7587 out->a2dp_compress_mute = false;
7588 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
7589 }
7590 pthread_mutex_unlock(&out->compr_mute_lock);
7591 }
7592 } else {
7593 // mute compress stream if suspended
7594 pthread_mutex_lock(&out->compr_mute_lock);
7595 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7596 (!out->a2dp_compress_mute)) {
7597 if (!out->standby) {
7598 ALOGD("%s: selecting speaker and muting stream", __func__);
7599 devices = out->devices;
7600 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
7601 left_p = out->volume_l;
7602 right_p = out->volume_r;
7603 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7604 compress_pause(out->compr);
7605 out_set_compr_volume(&out->stream, (float)0, (float)0);
7606 out->a2dp_compress_mute = true;
7607 select_devices(adev, out->usecase);
7608 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7609 compress_resume(out->compr);
7610 out->devices = devices;
7611 out->volume_l = left_p;
7612 out->volume_r = right_p;
7613 }
7614 }
7615 pthread_mutex_unlock(&out->compr_mute_lock);
7616 }
7617 ALOGV("%s: exit", __func__);
7618 return 0;
7619}
7620
7621int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
7622{
7623 int ret = 0;
7624
7625 lock_output_stream(out);
7626 pthread_mutex_lock(&adev->lock);
7627
7628 ret = check_a2dp_restore_l(adev, out, restore);
7629
7630 pthread_mutex_unlock(&adev->lock);
7631 pthread_mutex_unlock(&out->lock);
7632 return ret;
7633}
7634
Haynes Mathew George01156f92018-04-13 15:29:54 -07007635void adev_on_battery_status_changed(bool charging)
7636{
7637 pthread_mutex_lock(&adev->lock);
7638 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
7639 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08007640 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07007641 pthread_mutex_unlock(&adev->lock);
7642}
7643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007644static int adev_open(const hw_module_t *module, const char *name,
7645 hw_device_t **device)
7646{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307647 int ret;
7648
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007649 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007650 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
7651
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007652 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07007653 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007654 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07007655 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007656 ALOGD("%s: returning existing instance of adev", __func__);
7657 ALOGD("%s: exit", __func__);
7658 pthread_mutex_unlock(&adev_init_lock);
7659 return 0;
7660 }
7661
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007662 adev = calloc(1, sizeof(struct audio_device));
7663
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007664 if (!adev) {
7665 pthread_mutex_unlock(&adev_init_lock);
7666 return -ENOMEM;
7667 }
7668
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007669 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
7670
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05307671#ifdef DYNAMIC_LOG_ENABLED
7672 register_for_dynamic_logging("hal");
7673#endif
7674
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007675 adev->device.common.tag = HARDWARE_DEVICE_TAG;
7676 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7677 adev->device.common.module = (struct hw_module_t *)module;
7678 adev->device.common.close = adev_close;
7679
7680 adev->device.init_check = adev_init_check;
7681 adev->device.set_voice_volume = adev_set_voice_volume;
7682 adev->device.set_master_volume = adev_set_master_volume;
7683 adev->device.get_master_volume = adev_get_master_volume;
7684 adev->device.set_master_mute = adev_set_master_mute;
7685 adev->device.get_master_mute = adev_get_master_mute;
7686 adev->device.set_mode = adev_set_mode;
7687 adev->device.set_mic_mute = adev_set_mic_mute;
7688 adev->device.get_mic_mute = adev_get_mic_mute;
7689 adev->device.set_parameters = adev_set_parameters;
7690 adev->device.get_parameters = adev_get_parameters;
7691 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
7692 adev->device.open_output_stream = adev_open_output_stream;
7693 adev->device.close_output_stream = adev_close_output_stream;
7694 adev->device.open_input_stream = adev_open_input_stream;
7695 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307696 adev->device.create_audio_patch = adev_create_audio_patch;
7697 adev->device.release_audio_patch = adev_release_audio_patch;
7698 adev->device.get_audio_port = adev_get_audio_port;
7699 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007700 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307701 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007702
7703 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007704 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08007705 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007706 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007707 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007708 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08007709 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07007710 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307711 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07007712 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07007713 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007714 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08007715 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08007716 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007717 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05307718 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307719 adev->perf_lock_opts[0] = 0x101;
7720 adev->perf_lock_opts[1] = 0x20E;
7721 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007722 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007724 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07007725 adev->platform = platform_init(adev);
7726 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007727 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007728 free(adev->snd_dev_ref_cnt);
7729 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007730 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07007731 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7732 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08007733 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007734 return -EINVAL;
7735 }
Eric Laurentc4aef752013-09-12 17:45:53 -07007736
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307737 if (audio_extn_qaf_is_enabled()) {
7738 ret = audio_extn_qaf_init(adev);
7739 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007740 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307741 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007742 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307743 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7744 *device = NULL;
7745 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307746 return ret;
7747 }
7748
7749 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
7750 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
7751 }
7752
Eric Laurentc4aef752013-09-12 17:45:53 -07007753 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
7754 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
7755 if (adev->visualizer_lib == NULL) {
7756 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
7757 } else {
7758 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
7759 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007760 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007761 "visualizer_hal_start_output");
7762 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007763 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007764 "visualizer_hal_stop_output");
7765 }
7766 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05307767 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08007768 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007769 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307770 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007771 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07007772
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007773 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
7774 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
7775 if (adev->offload_effects_lib == NULL) {
7776 ALOGE("%s: DLOPEN failed for %s", __func__,
7777 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7778 } else {
7779 ALOGV("%s: DLOPEN successful for %s", __func__,
7780 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7781 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05307782 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007783 "offload_effects_bundle_hal_start_output");
7784 adev->offload_effects_stop_output =
7785 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
7786 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007787 adev->offload_effects_set_hpx_state =
7788 (int (*)(bool))dlsym(adev->offload_effects_lib,
7789 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05307790 adev->offload_effects_get_parameters =
7791 (void (*)(struct str_parms *, struct str_parms *))
7792 dlsym(adev->offload_effects_lib,
7793 "offload_effects_bundle_get_parameters");
7794 adev->offload_effects_set_parameters =
7795 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
7796 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007797 }
7798 }
7799
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007800 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
7801 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
7802 if (adev->adm_lib == NULL) {
7803 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
7804 } else {
7805 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
7806 adev->adm_init = (adm_init_t)
7807 dlsym(adev->adm_lib, "adm_init");
7808 adev->adm_deinit = (adm_deinit_t)
7809 dlsym(adev->adm_lib, "adm_deinit");
7810 adev->adm_register_input_stream = (adm_register_input_stream_t)
7811 dlsym(adev->adm_lib, "adm_register_input_stream");
7812 adev->adm_register_output_stream = (adm_register_output_stream_t)
7813 dlsym(adev->adm_lib, "adm_register_output_stream");
7814 adev->adm_deregister_stream = (adm_deregister_stream_t)
7815 dlsym(adev->adm_lib, "adm_deregister_stream");
7816 adev->adm_request_focus = (adm_request_focus_t)
7817 dlsym(adev->adm_lib, "adm_request_focus");
7818 adev->adm_abandon_focus = (adm_abandon_focus_t)
7819 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007820 adev->adm_set_config = (adm_set_config_t)
7821 dlsym(adev->adm_lib, "adm_set_config");
7822 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
7823 dlsym(adev->adm_lib, "adm_request_focus_v2");
7824 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
7825 dlsym(adev->adm_lib, "adm_is_noirq_avail");
7826 adev->adm_on_routing_change = (adm_on_routing_change_t)
7827 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007828 }
7829 }
7830
Mingming Yin514a8bc2014-07-29 15:22:21 -07007831 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007832 //initialize this to false for now,
7833 //this will be set to true through set param
7834 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07007835
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07007836 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007837 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007838 adev->dsp_bit_width_enforce_mode =
7839 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007840
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307841 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
7842 &adev->streams_output_cfg_list,
7843 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007844
Kiran Kandi910e1862013-10-29 13:29:42 -07007845 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007846
7847 char value[PROPERTY_VALUE_MAX];
7848 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007849 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007850 trial = atoi(value);
7851 if (period_size_is_plausible_for_low_latency(trial)) {
7852 pcm_config_low_latency.period_size = trial;
7853 pcm_config_low_latency.start_threshold = trial / 4;
7854 pcm_config_low_latency.avail_min = trial / 4;
7855 configured_low_latency_capture_period_size = trial;
7856 }
7857 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007858 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007859 trial = atoi(value);
7860 if (period_size_is_plausible_for_low_latency(trial)) {
7861 configured_low_latency_capture_period_size = trial;
7862 }
7863 }
7864
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08007865 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
7866
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007867 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007868 af_period_multiplier = atoi(value);
7869 if (af_period_multiplier < 0)
7870 af_period_multiplier = 2;
7871 else if (af_period_multiplier > 4)
7872 af_period_multiplier = 4;
7873
7874 ALOGV("new period_multiplier = %d", af_period_multiplier);
7875 }
7876
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007877 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007878 pthread_mutex_unlock(&adev_init_lock);
7879
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007880 if (adev->adm_init)
7881 adev->adm_data = adev->adm_init();
7882
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307883 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307884 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007885 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307886
7887 audio_extn_snd_mon_init();
7888 pthread_mutex_lock(&adev->lock);
7889 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
7890 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07007891 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
7892 /*
7893 * if the battery state callback happens before charging can be queried,
7894 * it will be guarded with the adev->lock held in the cb function and so
7895 * the callback value will reflect the latest state
7896 */
7897 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307898 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08007899 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
7900 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307901 /* Allocate memory for Device config params */
7902 adev->device_cfg_params = (struct audio_device_config_param*)
7903 calloc(platform_get_max_codec_backend(),
7904 sizeof(struct audio_device_config_param));
7905 if (adev->device_cfg_params == NULL)
7906 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307907
Eric Laurent994a6932013-07-17 11:51:42 -07007908 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007909 return 0;
7910}
7911
7912static struct hw_module_methods_t hal_module_methods = {
7913 .open = adev_open,
7914};
7915
7916struct audio_module HAL_MODULE_INFO_SYM = {
7917 .common = {
7918 .tag = HARDWARE_MODULE_TAG,
7919 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
7920 .hal_api_version = HARDWARE_HAL_API_VERSION,
7921 .id = AUDIO_HARDWARE_MODULE_ID,
7922 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08007923 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007924 .methods = &hal_module_methods,
7925 },
7926};