blob: ac4233de086cc0b60723b651445a7e9da7dd6a09 [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
356 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture"
Eric Laurentb23d5282013-05-14 15:27:20 -0700357};
358
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700359static const audio_usecase_t offload_usecases[] = {
360 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700361 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
362 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
363 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
364 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
365 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
366 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
367 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
368 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700369};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800370
Varun Balaraje49253e2017-07-06 19:48:56 +0530371static const audio_usecase_t interactive_usecases[] = {
372 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
373 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
374 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
375 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
376 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
377 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
378 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
379 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
380};
381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800382#define STRING_TO_ENUM(string) { #string, string }
383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800384struct string_to_enum {
385 const char *name;
386 uint32_t value;
387};
388
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700389static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800390 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800391 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
392 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
393 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700394 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800395 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
396 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800397 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700398 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
399 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
400 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
401 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
402 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
403 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
404 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
405 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
406 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
407 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
408 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800409};
410
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700411static const struct string_to_enum formats_name_to_enum_table[] = {
412 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
413 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
414 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700415 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
416 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
417 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700418 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800419 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
420 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700421 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800422};
423
424//list of all supported sample rates by HDMI specification.
425static const int out_hdmi_sample_rates[] = {
426 32000, 44100, 48000, 88200, 96000, 176400, 192000,
427};
428
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700429static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800430 STRING_TO_ENUM(32000),
431 STRING_TO_ENUM(44100),
432 STRING_TO_ENUM(48000),
433 STRING_TO_ENUM(88200),
434 STRING_TO_ENUM(96000),
435 STRING_TO_ENUM(176400),
436 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700437};
438
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700439static struct audio_device *adev = NULL;
440static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700441static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700442//cache last MBDRC cal step level
443static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700444
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530445static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
446static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800447static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530448static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530449
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700450static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
451 int flags __unused)
452{
453 int dir = 0;
454 switch (uc_id) {
455 case USECASE_AUDIO_RECORD_LOW_LATENCY:
456 dir = 1;
457 case USECASE_AUDIO_PLAYBACK_ULL:
458 break;
459 default:
460 return false;
461 }
462
463 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
464 PCM_PLAYBACK : PCM_CAPTURE);
465 if (adev->adm_is_noirq_avail)
466 return adev->adm_is_noirq_avail(adev->adm_data,
467 adev->snd_card, dev_id, dir);
468 return false;
469}
470
471static void register_out_stream(struct stream_out *out)
472{
473 struct audio_device *adev = out->dev;
474 if (is_offload_usecase(out->usecase) ||
475 !adev->adm_register_output_stream)
476 return;
477
478 // register stream first for backward compatibility
479 adev->adm_register_output_stream(adev->adm_data,
480 out->handle,
481 out->flags);
482
483 if (!adev->adm_set_config)
484 return;
485
486 if (out->realtime)
487 adev->adm_set_config(adev->adm_data,
488 out->handle,
489 out->pcm, &out->config);
490}
491
492static void register_in_stream(struct stream_in *in)
493{
494 struct audio_device *adev = in->dev;
495 if (!adev->adm_register_input_stream)
496 return;
497
498 adev->adm_register_input_stream(adev->adm_data,
499 in->capture_handle,
500 in->flags);
501
502 if (!adev->adm_set_config)
503 return;
504
505 if (in->realtime)
506 adev->adm_set_config(adev->adm_data,
507 in->capture_handle,
508 in->pcm,
509 &in->config);
510}
511
512static void request_out_focus(struct stream_out *out, long ns)
513{
514 struct audio_device *adev = out->dev;
515
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700516 if (adev->adm_request_focus_v2)
517 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
518 else if (adev->adm_request_focus)
519 adev->adm_request_focus(adev->adm_data, out->handle);
520}
521
522static void request_in_focus(struct stream_in *in, long ns)
523{
524 struct audio_device *adev = in->dev;
525
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700526 if (adev->adm_request_focus_v2)
527 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
528 else if (adev->adm_request_focus)
529 adev->adm_request_focus(adev->adm_data, in->capture_handle);
530}
531
532static void release_out_focus(struct stream_out *out)
533{
534 struct audio_device *adev = out->dev;
535
536 if (adev->adm_abandon_focus)
537 adev->adm_abandon_focus(adev->adm_data, out->handle);
538}
539
540static void release_in_focus(struct stream_in *in)
541{
542 struct audio_device *adev = in->dev;
543 if (adev->adm_abandon_focus)
544 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
545}
546
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530547static int parse_snd_card_status(struct str_parms *parms, int *card,
548 card_status_t *status)
549{
550 char value[32]={0};
551 char state[32]={0};
552
553 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
554 if (ret < 0)
555 return -1;
556
557 // sscanf should be okay as value is of max length 32.
558 // same as sizeof state.
559 if (sscanf(value, "%d,%s", card, state) < 2)
560 return -1;
561
562 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
563 CARD_STATUS_OFFLINE;
564 return 0;
565}
566
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700567static inline void adjust_frames_for_device_delay(struct stream_out *out,
568 uint32_t *dsp_frames) {
569 // Adjustment accounts for A2dp encoder latency with offload usecases
570 // Note: Encoder latency is returned in ms.
571 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
572 unsigned long offset =
573 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
574 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
575 }
576}
577
vivek mehtaa76401a2015-04-24 14:12:15 -0700578__attribute__ ((visibility ("default")))
579bool audio_hw_send_gain_dep_calibration(int level) {
580 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700581 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700582
583 pthread_mutex_lock(&adev_init_lock);
584
585 if (adev != NULL && adev->platform != NULL) {
586 pthread_mutex_lock(&adev->lock);
587 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700588
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530589 // cache level info for any of the use case which
590 // was not started.
591 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700592
vivek mehtaa76401a2015-04-24 14:12:15 -0700593 pthread_mutex_unlock(&adev->lock);
594 } else {
595 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
596 }
597
598 pthread_mutex_unlock(&adev_init_lock);
599
600 return ret_val;
601}
602
Ashish Jain5106d362016-05-11 19:23:33 +0530603static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
604{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800605 bool gapless_enabled = false;
606 const char *mixer_ctl_name = "Compress Gapless Playback";
607 struct mixer_ctl *ctl;
608
609 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700610 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530611
612 /*Disable gapless if its AV playback*/
613 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800614
615 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
616 if (!ctl) {
617 ALOGE("%s: Could not get ctl for mixer cmd - %s",
618 __func__, mixer_ctl_name);
619 return -EINVAL;
620 }
621
622 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
623 ALOGE("%s: Could not set gapless mode %d",
624 __func__, gapless_enabled);
625 return -EINVAL;
626 }
627 return 0;
628}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700629
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700630__attribute__ ((visibility ("default")))
631int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
632 int table_size) {
633 int ret_val = 0;
634 ALOGV("%s: enter ... ", __func__);
635
636 pthread_mutex_lock(&adev_init_lock);
637 if (adev == NULL) {
638 ALOGW("%s: adev is NULL .... ", __func__);
639 goto done;
640 }
641
642 pthread_mutex_lock(&adev->lock);
643 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
644 pthread_mutex_unlock(&adev->lock);
645done:
646 pthread_mutex_unlock(&adev_init_lock);
647 ALOGV("%s: exit ... ", __func__);
648 return ret_val;
649}
650
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700651static bool is_supported_format(audio_format_t format)
652{
Eric Laurent86e17132013-09-12 17:49:30 -0700653 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530654 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530655 format == AUDIO_FORMAT_AAC_LC ||
656 format == AUDIO_FORMAT_AAC_HE_V1 ||
657 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530658 format == AUDIO_FORMAT_AAC_ADTS_LC ||
659 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
660 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530661 format == AUDIO_FORMAT_AAC_LATM_LC ||
662 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
663 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530664 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
665 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530666 format == AUDIO_FORMAT_PCM_FLOAT ||
667 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700668 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530669 format == AUDIO_FORMAT_AC3 ||
670 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700671 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530672 format == AUDIO_FORMAT_DTS ||
673 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800674 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530675 format == AUDIO_FORMAT_ALAC ||
676 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530677 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530678 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800679 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530680 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700681 format == AUDIO_FORMAT_APTX ||
682 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800683 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700684
685 return false;
686}
687
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700688static inline bool is_mmap_usecase(audio_usecase_t uc_id)
689{
690 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
691 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
692}
693
Avinash Vaish71a8b972014-07-24 15:36:33 +0530694static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
695 struct audio_usecase *uc_info)
696{
697 struct listnode *node;
698 struct audio_usecase *usecase;
699
700 if (uc_info == NULL)
701 return -EINVAL;
702
703 /* Re-route all voice usecases on the shared backend other than the
704 specified usecase to new snd devices */
705 list_for_each(node, &adev->usecase_list) {
706 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800707 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530708 enable_audio_route(adev, usecase);
709 }
710 return 0;
711}
712
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530713static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530714{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530715 ALOGV("%s", __func__);
716 audio_route_apply_and_update_path(adev->audio_route,
717 "asrc-mode");
718 adev->asrc_mode_enabled = true;
719}
720
721static void disable_asrc_mode(struct audio_device *adev)
722{
723 ALOGV("%s", __func__);
724 audio_route_reset_and_update_path(adev->audio_route,
725 "asrc-mode");
726 adev->asrc_mode_enabled = false;
727}
728
729/*
730 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
731 * 44.1 or Native DSD backends are enabled for any of current use case.
732 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
733 * - Disable current mix path use case(Headphone backend) and re-enable it with
734 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
735 * e.g. Naitve DSD or Headphone 44.1 -> + 48
736 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530737static void check_and_set_asrc_mode(struct audio_device *adev,
738 struct audio_usecase *uc_info,
739 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530740{
741 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530742 int i, num_new_devices = 0;
743 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
744 /*
745 *Split snd device for new combo use case
746 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
747 */
748 if (platform_split_snd_device(adev->platform,
749 snd_device,
750 &num_new_devices,
751 split_new_snd_devices) == 0) {
752 for (i = 0; i < num_new_devices; i++)
753 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
754 } else {
755 int new_backend_idx = platform_get_backend_index(snd_device);
756 if (((new_backend_idx == HEADPHONE_BACKEND) ||
757 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
758 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
759 !adev->asrc_mode_enabled) {
760 struct listnode *node = NULL;
761 struct audio_usecase *uc = NULL;
762 struct stream_out *curr_out = NULL;
763 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
764 int i, num_devices, ret = 0;
765 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530766
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530767 list_for_each(node, &adev->usecase_list) {
768 uc = node_to_item(node, struct audio_usecase, list);
769 curr_out = (struct stream_out*) uc->stream.out;
770 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
771 /*
772 *Split snd device for existing combo use case
773 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
774 */
775 ret = platform_split_snd_device(adev->platform,
776 uc->out_snd_device,
777 &num_devices,
778 split_snd_devices);
779 if (ret < 0 || num_devices == 0) {
780 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
781 split_snd_devices[0] = uc->out_snd_device;
782 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800783 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530784 for (i = 0; i < num_devices; i++) {
785 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
786 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
787 if((new_backend_idx == HEADPHONE_BACKEND) &&
788 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
789 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
790 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
791 __func__);
792 enable_asrc_mode(adev);
793 break;
794 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
795 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
796 (usecase_backend_idx == HEADPHONE_BACKEND)) {
797 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
798 __func__);
799 disable_audio_route(adev, uc);
800 disable_snd_device(adev, uc->out_snd_device);
801 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
802 if (new_backend_idx == DSD_NATIVE_BACKEND)
803 audio_route_apply_and_update_path(adev->audio_route,
804 "hph-true-highquality-mode");
805 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
806 (curr_out->bit_width >= 24))
807 audio_route_apply_and_update_path(adev->audio_route,
808 "hph-highquality-mode");
809 enable_asrc_mode(adev);
810 enable_snd_device(adev, uc->out_snd_device);
811 enable_audio_route(adev, uc);
812 break;
813 }
814 }
815 // reset split devices count
816 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800817 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530818 if (adev->asrc_mode_enabled)
819 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530820 }
821 }
822 }
823}
824
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700825#ifdef DYNAMIC_ECNS_ENABLED
826static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
827 struct audio_effect_config effect_config,
828 unsigned int param_value)
829{
830 char mixer_ctl_name[] = "Audio Effect";
831 struct mixer_ctl *ctl;
832 long set_values[6];
833 struct stream_in *in = adev->active_input;
834
835 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
836 if (!ctl) {
837 ALOGE("%s: Could not get mixer ctl - %s",
838 __func__, mixer_ctl_name);
839 return -EINVAL;
840 }
841
842 set_values[0] = 1; //0:Rx 1:Tx
843 set_values[1] = in->app_type_cfg.app_type;
844 set_values[2] = (long)effect_config.module_id;
845 set_values[3] = (long)effect_config.instance_id;
846 set_values[4] = (long)effect_config.param_id;
847 set_values[5] = param_value;
848
849 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
850
851 return 0;
852
853}
854
855static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
856 int effect_type, unsigned int *param_value)
857{
858 int ret = 0;
859 struct audio_effect_config other_effect_config;
860 struct audio_usecase *usecase = NULL;
861 struct stream_in *in = adev->active_input;
862
863 usecase = get_usecase_from_list(adev, in->usecase);
864 if (!usecase)
865 return -EINVAL;
866
867 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
868 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
869 if (ret < 0) {
870 ALOGE("%s Failed to get effect params %d", __func__, ret);
871 return ret;
872 }
873
874 if (module_id == other_effect_config.module_id) {
875 //Same module id for AEC/NS. Values need to be combined
876 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
877 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
878 *param_value |= other_effect_config.param_value;
879 }
880 }
881
882 return ret;
883}
884
885static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
886{
887 struct audio_effect_config effect_config;
888 struct audio_usecase *usecase = NULL;
889 int ret = 0;
890 unsigned int param_value = 0;
891 struct stream_in *in = adev->active_input;
892
893 if (!in) {
894 ALOGE("%s: Invalid input stream", __func__);
895 return -EINVAL;
896 }
897
898 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
899
900 usecase = get_usecase_from_list(adev, in->usecase);
901
902 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
903 if (ret < 0) {
904 ALOGE("%s Failed to get module id %d", __func__, ret);
905 return ret;
906 }
907 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
908 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
909
910 if(enable)
911 param_value = effect_config.param_value;
912
913 /*Special handling for AEC & NS effects Param values need to be
914 updated if module ids are same*/
915
916 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
917 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
918 if (ret < 0)
919 return ret;
920 }
921
922 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
923
924 return ret;
925}
926
927static void check_and_enable_effect(struct audio_device *adev)
928{
929
930 if (adev->active_input->enable_aec) {
931 enable_disable_effect(adev, EFFECT_AEC, true);
932 }
933
934 if (adev->active_input->enable_ns &&
935 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
936 enable_disable_effect(adev, EFFECT_NS, true);
937 }
938}
939#else
940#define enable_disable_effect(x, y, z) ENOSYS
941#define check_and_enable_effect(x) ENOSYS
942#endif
943
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700944int pcm_ioctl(struct pcm *pcm, int request, ...)
945{
946 va_list ap;
947 void * arg;
948 int pcm_fd = *(int*)pcm;
949
950 va_start(ap, request);
951 arg = va_arg(ap, void *);
952 va_end(ap);
953
954 return ioctl(pcm_fd, request, arg);
955}
956
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700957int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700958 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800959{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700960 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700961 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530962 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800963
964 if (usecase == NULL)
965 return -EINVAL;
966
967 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
968
Surendar Karka93cd25a2018-08-28 14:21:37 +0530969 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700970 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800971 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700972 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800973
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800974#ifdef DS1_DOLBY_DAP_ENABLED
975 audio_extn_dolby_set_dmid(adev);
976 audio_extn_dolby_set_endpoint(adev);
977#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700978 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700979 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530980 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700981 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530982 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530983 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
984 out = usecase->stream.out;
985 if (out && out->compr)
986 audio_extn_utils_compress_set_clk_rec_mode(usecase);
987 }
988
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800989 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700990 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700991 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700992 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800993 ALOGV("%s: exit", __func__);
994 return 0;
995}
996
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700997int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700998 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800999{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001000 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001001 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001002
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301003 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001004 return -EINVAL;
1005
1006 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301007 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001008 snd_device = usecase->in_snd_device;
1009 else
1010 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001011 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001012 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001013 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001014 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001015 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301016 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001017 ALOGV("%s: exit", __func__);
1018 return 0;
1019}
1020
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001021int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001022 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001023{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301024 int i, num_devices = 0;
1025 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001026 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1027
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001028 if (snd_device < SND_DEVICE_MIN ||
1029 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001030 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001031 return -EINVAL;
1032 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001033
1034 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001035
1036 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
1037 ALOGE("%s: Invalid sound device returned", __func__);
1038 return -EINVAL;
1039 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001040 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -07001041 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001042 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001043 return 0;
1044 }
1045
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301046
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001047 if (audio_extn_spkr_prot_is_enabled())
1048 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001049
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001050 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1051 audio_extn_spkr_prot_is_enabled()) {
1052 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001053 adev->snd_dev_ref_cnt[snd_device]--;
1054 return -EINVAL;
1055 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001056 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001057 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001058 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001059 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001060 return -EINVAL;
1061 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001062 } else if (platform_split_snd_device(adev->platform,
1063 snd_device,
1064 &num_devices,
1065 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301066 for (i = 0; i < num_devices; i++) {
1067 enable_snd_device(adev, new_snd_devices[i]);
1068 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001069 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001070 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301071
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301072
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301073 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1074 (audio_extn_a2dp_start_playback() < 0)) {
1075 ALOGE(" fail to configure A2dp control path ");
1076 return -EINVAL;
1077 }
1078
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001079 /* due to the possibility of calibration overwrite between listen
1080 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001081 audio_extn_sound_trigger_update_device_status(snd_device,
1082 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301083 audio_extn_listen_update_device_status(snd_device,
1084 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001085 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001086 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001087 audio_extn_sound_trigger_update_device_status(snd_device,
1088 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301089 audio_extn_listen_update_device_status(snd_device,
1090 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001091 return -EINVAL;
1092 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001093 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001094 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301095
1096 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1097 !adev->native_playback_enabled &&
1098 audio_is_true_native_stream_active(adev)) {
1099 ALOGD("%s: %d: napb: enabling native mode in hardware",
1100 __func__, __LINE__);
1101 audio_route_apply_and_update_path(adev->audio_route,
1102 "true-native-mode");
1103 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301104 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301105 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1106 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001107 (audio_extn_ffv_get_stream() == adev->active_input)) {
1108 ALOGD("%s: init ec ref loopback", __func__);
1109 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1110 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001111 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112 return 0;
1113}
1114
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001115int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001116 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301118 int i, num_devices = 0;
1119 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001120 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1121
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001122 if (snd_device < SND_DEVICE_MIN ||
1123 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001124 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001125 return -EINVAL;
1126 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001127 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1128 ALOGE("%s: device ref cnt is already 0", __func__);
1129 return -EINVAL;
1130 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001131
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001132 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001133
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001134 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1135 ALOGE("%s: Invalid sound device returned", __func__);
1136 return -EINVAL;
1137 }
1138
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001139 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001140 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301141
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001142 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1143 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001144 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001145
1146 // when speaker device is disabled, reset swap.
1147 // will be renabled on usecase start
1148 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001149 } else if (platform_split_snd_device(adev->platform,
1150 snd_device,
1151 &num_devices,
1152 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301153 for (i = 0; i < num_devices; i++) {
1154 disable_snd_device(adev, new_snd_devices[i]);
1155 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001156 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001157 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001158 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001159
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301160 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1161 audio_extn_a2dp_stop_playback();
1162
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001163 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301164 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301165 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1166 adev->native_playback_enabled) {
1167 ALOGD("%s: %d: napb: disabling native mode in hardware",
1168 __func__, __LINE__);
1169 audio_route_reset_and_update_path(adev->audio_route,
1170 "true-native-mode");
1171 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301172 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1173 adev->asrc_mode_enabled) {
1174 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301175 disable_asrc_mode(adev);
1176 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301177 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001178 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1179 (audio_extn_ffv_get_stream() == adev->active_input)) {
1180 ALOGD("%s: deinit ec ref loopback", __func__);
1181 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1182 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001183 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001184 audio_extn_sound_trigger_update_device_status(snd_device,
1185 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301186 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001187 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001188 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001189
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001190 return 0;
1191}
1192
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001193/*
1194 legend:
1195 uc - existing usecase
1196 new_uc - new usecase
1197 d1, d11, d2 - SND_DEVICE enums
1198 a1, a2 - corresponding ANDROID device enums
1199 B1, B2 - backend strings
1200
1201case 1
1202 uc->dev d1 (a1) B1
1203 new_uc->dev d1 (a1), d2 (a2) B1, B2
1204
1205 resolution: disable and enable uc->dev on d1
1206
1207case 2
1208 uc->dev d1 (a1) B1
1209 new_uc->dev d11 (a1) B1
1210
1211 resolution: need to switch uc since d1 and d11 are related
1212 (e.g. speaker and voice-speaker)
1213 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1214
1215case 3
1216 uc->dev d1 (a1) B1
1217 new_uc->dev d2 (a2) B2
1218
1219 resolution: no need to switch uc
1220
1221case 4
1222 uc->dev d1 (a1) B1
1223 new_uc->dev d2 (a2) B1
1224
1225 resolution: disable enable uc-dev on d2 since backends match
1226 we cannot enable two streams on two different devices if they
1227 share the same backend. e.g. if offload is on speaker device using
1228 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1229 using the same backend, offload must also be switched to voice-handset.
1230
1231case 5
1232 uc->dev d1 (a1) B1
1233 new_uc->dev d1 (a1), d2 (a2) B1
1234
1235 resolution: disable enable uc-dev on d2 since backends match
1236 we cannot enable two streams on two different devices if they
1237 share the same backend.
1238
1239case 6
1240 uc->dev d1 (a1) B1
1241 new_uc->dev d2 (a1) B2
1242
1243 resolution: no need to switch
1244
1245case 7
1246 uc->dev d1 (a1), d2 (a2) B1, B2
1247 new_uc->dev d1 (a1) B1
1248
1249 resolution: no need to switch
1250
1251*/
1252static snd_device_t derive_playback_snd_device(void * platform,
1253 struct audio_usecase *uc,
1254 struct audio_usecase *new_uc,
1255 snd_device_t new_snd_device)
1256{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301257 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001258
1259 snd_device_t d1 = uc->out_snd_device;
1260 snd_device_t d2 = new_snd_device;
1261
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301262 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301263 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301264 a1 = uc->stream.inout->out_config.devices;
1265 a2 = new_uc->stream.inout->out_config.devices;
1266 break;
1267 default :
1268 a1 = uc->stream.out->devices;
1269 a2 = new_uc->stream.out->devices;
1270 break;
1271 }
1272
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001273 // Treat as a special case when a1 and a2 are not disjoint
1274 if ((a1 != a2) && (a1 & a2)) {
1275 snd_device_t d3[2];
1276 int num_devices = 0;
1277 int ret = platform_split_snd_device(platform,
1278 popcount(a1) > 1 ? d1 : d2,
1279 &num_devices,
1280 d3);
1281 if (ret < 0) {
1282 if (ret != -ENOSYS) {
1283 ALOGW("%s failed to split snd_device %d",
1284 __func__,
1285 popcount(a1) > 1 ? d1 : d2);
1286 }
1287 goto end;
1288 }
1289
1290 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1291 // But if it does happen, we need to give priority to d2 if
1292 // the combo devices active on the existing usecase share a backend.
1293 // This is because we cannot have a usecase active on a combo device
1294 // and a new usecase requests one device in this combo pair.
1295 if (platform_check_backends_match(d3[0], d3[1])) {
1296 return d2; // case 5
1297 } else {
1298 return d1; // case 1
1299 }
1300 } else {
1301 if (platform_check_backends_match(d1, d2)) {
1302 return d2; // case 2, 4
1303 } else {
1304 return d1; // case 6, 3
1305 }
1306 }
1307
1308end:
1309 return d2; // return whatever was calculated before.
1310}
1311
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001312static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301313 struct audio_usecase *uc_info,
1314 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001315{
1316 struct listnode *node;
1317 struct audio_usecase *usecase;
1318 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301319 snd_device_t uc_derive_snd_device;
1320 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001321 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001322 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301323 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001324 /*
1325 * This function is to make sure that all the usecases that are active on
1326 * the hardware codec backend are always routed to any one device that is
1327 * handled by the hardware codec.
1328 * For example, if low-latency and deep-buffer usecases are currently active
1329 * on speaker and out_set_parameters(headset) is received on low-latency
1330 * output, then we have to make sure deep-buffer is also switched to headset,
1331 * because of the limitation that both the devices cannot be enabled
1332 * at the same time as they share the same backend.
1333 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001334 /*
1335 * This call is to check if we need to force routing for a particular stream
1336 * If there is a backend configuration change for the device when a
1337 * new stream starts, then ADM needs to be closed and re-opened with the new
1338 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001339 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001340 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001341 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1342 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301343 /* For a2dp device reconfigure all active sessions
1344 * with new AFE encoder format based on a2dp state
1345 */
1346 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1347 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1348 audio_extn_a2dp_is_force_device_switch()) {
1349 force_routing = true;
1350 force_restart_session = true;
1351 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301352 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1353
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001354 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001355 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001356 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001357 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1358 switch_device[i] = false;
1359
1360 list_for_each(node, &adev->usecase_list) {
1361 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001362
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301363 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1364 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301365 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301366 platform_get_snd_device_name(usecase->out_snd_device),
1367 platform_check_backends_match(snd_device, usecase->out_snd_device));
kunleizef820832018-08-10 11:08:03 +08001368 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301369 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1370 usecase, uc_info, snd_device);
1371 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1372 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1373 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1374 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1375 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1376 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1377 ((force_restart_session) ||
1378 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301379 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1380 __func__, use_case_table[usecase->id],
1381 platform_get_snd_device_name(usecase->out_snd_device));
1382 disable_audio_route(adev, usecase);
1383 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301384 /* Enable existing usecase on derived playback device */
1385 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301386 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301387 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001388 }
1389 }
1390
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301391 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1392 num_uc_to_switch);
1393
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001394 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001395 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001396
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301397 /* Make sure the previous devices to be disabled first and then enable the
1398 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001399 list_for_each(node, &adev->usecase_list) {
1400 usecase = node_to_item(node, struct audio_usecase, list);
1401 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001402 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001403 }
1404 }
1405
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001406 list_for_each(node, &adev->usecase_list) {
1407 usecase = node_to_item(node, struct audio_usecase, list);
1408 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301409 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001410 }
1411 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001412
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001413 /* Re-route all the usecases on the shared backend other than the
1414 specified usecase to new snd devices */
1415 list_for_each(node, &adev->usecase_list) {
1416 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301417 /* Update the out_snd_device only before enabling the audio route */
1418 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301419 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301420 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301421 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301422 use_case_table[usecase->id],
1423 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001424 /* Update voc calibration before enabling VoIP route */
1425 if (usecase->type == VOIP_CALL)
1426 status = platform_switch_voice_call_device_post(adev->platform,
1427 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001428 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301429 enable_audio_route(adev, usecase);
kunleizcf983df2018-03-19 16:28:09 +08001430 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1431 out_set_voip_volume(&usecase->stream.out->stream,
1432 usecase->stream.out->volume_l,
1433 usecase->stream.out->volume_r);
1434 }
Yidong Huang7939a3b2018-01-23 17:32:30 +08001435 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1436 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1437 if (parms)
1438 audio_extn_fm_set_parameters(adev, parms);
1439 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301440 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001441 }
1442 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001443 }
1444}
1445
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301446static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001447 struct audio_usecase *uc_info,
1448 snd_device_t snd_device)
1449{
1450 struct listnode *node;
1451 struct audio_usecase *usecase;
1452 bool switch_device[AUDIO_USECASE_MAX];
1453 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301454 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001455 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001456
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301457 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1458 snd_device);
1459 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301460
1461 /*
1462 * Make sure out devices is checked against out codec backend device and
1463 * also in devices against in codec backend. Checking out device against in
1464 * codec backend or vice versa causes issues.
1465 */
1466 if (uc_info->type == PCM_CAPTURE)
1467 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001468 /*
1469 * This function is to make sure that all the active capture usecases
1470 * are always routed to the same input sound device.
1471 * For example, if audio-record and voice-call usecases are currently
1472 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1473 * is received for voice call then we have to make sure that audio-record
1474 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1475 * because of the limitation that two devices cannot be enabled
1476 * at the same time if they share the same backend.
1477 */
1478 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1479 switch_device[i] = false;
1480
1481 list_for_each(node, &adev->usecase_list) {
1482 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301483 /*
1484 * TODO: Enhance below condition to handle BT sco/USB multi recording
1485 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001486 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001487 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301488 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301489 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301490 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301491 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001492 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001493 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1494 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001495 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001496 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001497 switch_device[usecase->id] = true;
1498 num_uc_to_switch++;
1499 }
1500 }
1501
1502 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001503 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001504
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301505 /* Make sure the previous devices to be disabled first and then enable the
1506 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001507 list_for_each(node, &adev->usecase_list) {
1508 usecase = node_to_item(node, struct audio_usecase, list);
1509 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001510 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001511 }
1512 }
1513
1514 list_for_each(node, &adev->usecase_list) {
1515 usecase = node_to_item(node, struct audio_usecase, list);
1516 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001517 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001518 }
1519 }
1520
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001521 /* Re-route all the usecases on the shared backend other than the
1522 specified usecase to new snd devices */
1523 list_for_each(node, &adev->usecase_list) {
1524 usecase = node_to_item(node, struct audio_usecase, list);
1525 /* Update the in_snd_device only before enabling the audio route */
1526 if (switch_device[usecase->id] ) {
1527 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001528 if (usecase->type != VOICE_CALL) {
1529 /* Update voc calibration before enabling VoIP route */
1530 if (usecase->type == VOIP_CALL)
1531 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001532 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001533 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301534 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001535 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001536 }
1537 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001538 }
1539}
1540
Mingming Yin3a941d42016-02-17 18:08:05 -08001541static void reset_hdmi_sink_caps(struct stream_out *out) {
1542 int i = 0;
1543
1544 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1545 out->supported_channel_masks[i] = 0;
1546 }
1547 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1548 out->supported_formats[i] = 0;
1549 }
1550 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1551 out->supported_sample_rates[i] = 0;
1552 }
1553}
1554
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001555/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001556static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001557{
Mingming Yin3a941d42016-02-17 18:08:05 -08001558 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001559 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001560
Mingming Yin3a941d42016-02-17 18:08:05 -08001561 reset_hdmi_sink_caps(out);
1562
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001563 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001564 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001565 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001566 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001567 }
1568
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001569 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001570 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001571 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001572 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001573 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1574 case 6:
1575 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1576 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1577 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1578 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1579 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1580 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001581 break;
1582 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001583 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001584 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001585 break;
1586 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001587
1588 // check channel format caps
1589 i = 0;
1590 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1591 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1592 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1593 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1594 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1595 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1596 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1597 }
1598
Ben Romberger1aaaf862017-04-06 17:49:46 -07001599 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1600 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1601 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1602 }
1603
Mingming Yin3a941d42016-02-17 18:08:05 -08001604 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1605 ALOGV(":%s HDMI supports DTS format", __func__);
1606 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1607 }
1608
1609 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1610 ALOGV(":%s HDMI supports DTS HD format", __func__);
1611 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1612 }
1613
Naresh Tanniru928f0862017-04-07 16:44:23 -07001614 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1615 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1616 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1617 }
1618
Mingming Yin3a941d42016-02-17 18:08:05 -08001619
1620 // check sample rate caps
1621 i = 0;
1622 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1623 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1624 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1625 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1626 }
1627 }
1628
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001629 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001630}
1631
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001632static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1633 uint32_t *supported_sample_rates __unused,
1634 uint32_t max_rates __unused)
1635{
1636 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1637 supported_sample_rates,
1638 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301639 ssize_t i = 0;
1640
1641 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001642 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1643 supported_sample_rates[i]);
1644 }
1645 return count;
1646}
1647
1648static inline int read_usb_sup_channel_masks(bool is_playback,
1649 audio_channel_mask_t *supported_channel_masks,
1650 uint32_t max_masks)
1651{
1652 int channels = audio_extn_usb_get_max_channels(is_playback);
1653 int channel_count;
1654 uint32_t num_masks = 0;
1655 if (channels > MAX_HIFI_CHANNEL_COUNT)
1656 channels = MAX_HIFI_CHANNEL_COUNT;
1657
1658 if (is_playback) {
1659 // For playback we never report mono because the framework always outputs stereo
1660 channel_count = DEFAULT_CHANNEL_COUNT;
1661 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1662 // above 2 but we want indexed masks here. So we
1663 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1664 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1665 }
1666 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1667 supported_channel_masks[num_masks++] =
1668 audio_channel_mask_for_index_assignment_from_count(channel_count);
1669 }
1670 } else {
1671 // For capture we report all supported channel masks from 1 channel up.
1672 channel_count = MIN_CHANNEL_COUNT;
1673 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1674 // indexed mask
1675 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1676 supported_channel_masks[num_masks++] =
1677 audio_channel_in_mask_from_count(channel_count);
1678 }
1679 }
1680 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1681 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1682 return num_masks;
1683}
1684
1685static inline int read_usb_sup_formats(bool is_playback __unused,
1686 audio_format_t *supported_formats,
1687 uint32_t max_formats __unused)
1688{
1689 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1690 switch (bitwidth) {
1691 case 24:
1692 // XXX : usb.c returns 24 for s24 and s24_le?
1693 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1694 break;
1695 case 32:
1696 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1697 break;
1698 case 16:
1699 default :
1700 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1701 break;
1702 }
1703 ALOGV("%s: %s supported format %d", __func__,
1704 is_playback ? "P" : "C", bitwidth);
1705 return 1;
1706}
1707
1708static inline int read_usb_sup_params_and_compare(bool is_playback,
1709 audio_format_t *format,
1710 audio_format_t *supported_formats,
1711 uint32_t max_formats,
1712 audio_channel_mask_t *mask,
1713 audio_channel_mask_t *supported_channel_masks,
1714 uint32_t max_masks,
1715 uint32_t *rate,
1716 uint32_t *supported_sample_rates,
1717 uint32_t max_rates) {
1718 int ret = 0;
1719 int num_formats;
1720 int num_masks;
1721 int num_rates;
1722 int i;
1723
1724 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1725 max_formats);
1726 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1727 max_masks);
1728
1729 num_rates = read_usb_sup_sample_rates(is_playback,
1730 supported_sample_rates, max_rates);
1731
1732#define LUT(table, len, what, dflt) \
1733 for (i=0; i<len && (table[i] != what); i++); \
1734 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1735
1736 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1737 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1738 LUT(supported_sample_rates, num_rates, *rate, 0);
1739
1740#undef LUT
1741 return ret < 0 ? -EINVAL : 0; // HACK TBD
1742}
1743
Alexy Josephb1379942016-01-29 15:49:38 -08001744audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001745 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001746{
1747 struct audio_usecase *usecase;
1748 struct listnode *node;
1749
1750 list_for_each(node, &adev->usecase_list) {
1751 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001752 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001753 ALOGV("%s: usecase id %d", __func__, usecase->id);
1754 return usecase->id;
1755 }
1756 }
1757 return USECASE_INVALID;
1758}
1759
Alexy Josephb1379942016-01-29 15:49:38 -08001760struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001761 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001762{
1763 struct audio_usecase *usecase;
1764 struct listnode *node;
1765
1766 list_for_each(node, &adev->usecase_list) {
1767 usecase = node_to_item(node, struct audio_usecase, list);
1768 if (usecase->id == uc_id)
1769 return usecase;
1770 }
1771 return NULL;
1772}
1773
Dhananjay Kumard4833242016-10-06 22:09:12 +05301774struct stream_in *get_next_active_input(const struct audio_device *adev)
1775{
1776 struct audio_usecase *usecase;
1777 struct listnode *node;
1778
1779 list_for_each_reverse(node, &adev->usecase_list) {
1780 usecase = node_to_item(node, struct audio_usecase, list);
1781 if (usecase->type == PCM_CAPTURE)
1782 return usecase->stream.in;
1783 }
1784 return NULL;
1785}
1786
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301787/*
1788 * is a true native playback active
1789 */
1790bool audio_is_true_native_stream_active(struct audio_device *adev)
1791{
1792 bool active = false;
1793 int i = 0;
1794 struct listnode *node;
1795
1796 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1797 ALOGV("%s:napb: not in true mode or non hdphones device",
1798 __func__);
1799 active = false;
1800 goto exit;
1801 }
1802
1803 list_for_each(node, &adev->usecase_list) {
1804 struct audio_usecase *uc;
1805 uc = node_to_item(node, struct audio_usecase, list);
1806 struct stream_out *curr_out =
1807 (struct stream_out*) uc->stream.out;
1808
1809 if (curr_out && PCM_PLAYBACK == uc->type) {
1810 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1811 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1812 uc->id, curr_out->sample_rate,
1813 curr_out->bit_width,
1814 platform_get_snd_device_name(uc->out_snd_device));
1815
1816 if (is_offload_usecase(uc->id) &&
1817 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1818 active = true;
1819 ALOGD("%s:napb:native stream detected", __func__);
1820 }
1821 }
1822 }
1823exit:
1824 return active;
1825}
1826
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001827uint32_t adev_get_dsp_bit_width_enforce_mode()
1828{
1829 if (adev == NULL) {
1830 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1831 return 0;
1832 }
1833 return adev->dsp_bit_width_enforce_mode;
1834}
1835
1836static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1837{
1838 char value[PROPERTY_VALUE_MAX];
1839 int trial;
1840 uint32_t dsp_bit_width_enforce_mode = 0;
1841
1842 if (!mixer) {
1843 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1844 __func__);
1845 return 0;
1846 }
1847
1848 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1849 value, NULL) > 0) {
1850 trial = atoi(value);
1851 switch (trial) {
1852 case 16:
1853 dsp_bit_width_enforce_mode = 16;
1854 break;
1855 case 24:
1856 dsp_bit_width_enforce_mode = 24;
1857 break;
1858 case 32:
1859 dsp_bit_width_enforce_mode = 32;
1860 break;
1861 default:
1862 dsp_bit_width_enforce_mode = 0;
1863 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1864 break;
1865 }
1866 }
1867
1868 return dsp_bit_width_enforce_mode;
1869}
1870
1871static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1872 uint32_t enforce_mode,
1873 bool enable)
1874{
1875 struct mixer_ctl *ctl = NULL;
1876 const char *mixer_ctl_name = "ASM Bit Width";
1877 uint32_t asm_bit_width_mode = 0;
1878
1879 if (enforce_mode == 0) {
1880 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1881 return;
1882 }
1883
1884 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1885 if (!ctl) {
1886 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1887 __func__, mixer_ctl_name);
1888 return;
1889 }
1890
1891 if (enable)
1892 asm_bit_width_mode = enforce_mode;
1893 else
1894 asm_bit_width_mode = 0;
1895
1896 ALOGV("%s DSP bit width feature status is %d width=%d",
1897 __func__, enable, asm_bit_width_mode);
1898 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1899 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1900 asm_bit_width_mode);
1901
1902 return;
1903}
1904
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301905/*
1906 * if native DSD playback active
1907 */
1908bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1909{
1910 bool active = false;
1911 struct listnode *node = NULL;
1912 struct audio_usecase *uc = NULL;
1913 struct stream_out *curr_out = NULL;
1914
1915 list_for_each(node, &adev->usecase_list) {
1916 uc = node_to_item(node, struct audio_usecase, list);
1917 curr_out = (struct stream_out*) uc->stream.out;
1918
1919 if (curr_out && PCM_PLAYBACK == uc->type &&
1920 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1921 active = true;
1922 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301923 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301924 }
1925 }
1926 return active;
1927}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301928
1929static bool force_device_switch(struct audio_usecase *usecase)
1930{
1931 bool ret = false;
1932 bool is_it_true_mode = false;
1933
Zhou Song30f2c3e2018-02-08 14:02:15 +08001934 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05301935 usecase->type == TRANSCODE_LOOPBACK_RX ||
1936 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08001937 return false;
1938 }
1939
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001940 if(usecase->stream.out == NULL) {
1941 ALOGE("%s: stream.out is NULL", __func__);
1942 return false;
1943 }
1944
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301945 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001946 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1947 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1948 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301949 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1950 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1951 (!is_it_true_mode && adev->native_playback_enabled)){
1952 ret = true;
1953 ALOGD("napb: time to toggle native mode");
1954 }
1955 }
1956
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301957 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301958 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1959 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001960 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301961 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301962 ALOGD("Force a2dp device switch to update new encoder config");
1963 ret = true;
1964 }
1965
Manish Dewangan671a4202017-08-18 17:30:46 +05301966 if (usecase->stream.out->stream_config_changed) {
1967 ALOGD("Force stream_config_changed to update iec61937 transmission config");
1968 return true;
1969 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301970 return ret;
1971}
1972
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301973bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1974{
1975 bool ret=false;
1976 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1977 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1978 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1979 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1980 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1981 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1982 ret = true;
1983
1984 return ret;
1985}
1986
1987bool is_a2dp_device(snd_device_t out_snd_device)
1988{
1989 bool ret=false;
1990 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1991 ret = true;
1992
1993 return ret;
1994}
1995
1996bool is_bt_soc_on(struct audio_device *adev)
1997{
1998 struct mixer_ctl *ctl;
1999 char *mixer_ctl_name = "BT SOC status";
2000 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2001 bool bt_soc_status = true;
2002 if (!ctl) {
2003 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2004 __func__, mixer_ctl_name);
2005 /*This is to ensure we dont break targets which dont have the kernel change*/
2006 return true;
2007 }
2008 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2009 ALOGD("BT SOC status: %d",bt_soc_status);
2010 return bt_soc_status;
2011}
2012
2013int out_standby_l(struct audio_stream *stream);
2014
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002015int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002017 snd_device_t out_snd_device = SND_DEVICE_NONE;
2018 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002019 struct audio_usecase *usecase = NULL;
2020 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002021 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002022 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302023 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002024 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002025 int status = 0;
Jhansi Konathala902fc412018-09-05 13:21:44 +05302026 audio_devices_t audio_device = AUDIO_DEVICE_NONE;
2027 audio_channel_mask_t channel_mask = AUDIO_CHANNEL_NONE;
2028 int sample_rate = 0;
2029 int acdb_id = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302031 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2032
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002033 usecase = get_usecase_from_list(adev, uc_id);
2034 if (usecase == NULL) {
2035 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2036 return -EINVAL;
2037 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002039 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002040 (usecase->type == VOIP_CALL) ||
2041 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302042 if(usecase->stream.out == NULL) {
2043 ALOGE("%s: stream.out is NULL", __func__);
2044 return -EINVAL;
2045 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002046 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002047 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002048 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002049 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302050 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302051 if (usecase->stream.inout == NULL) {
2052 ALOGE("%s: stream.inout is NULL", __func__);
2053 return -EINVAL;
2054 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302055 stream_out.devices = usecase->stream.inout->out_config.devices;
2056 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2057 stream_out.format = usecase->stream.inout->out_config.format;
2058 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2059 out_snd_device = platform_get_output_snd_device(adev->platform,
2060 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302061 usecase->devices = out_snd_device;
2062 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2063 if (usecase->stream.inout == NULL) {
2064 ALOGE("%s: stream.inout is NULL", __func__);
2065 return -EINVAL;
2066 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302067 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302068 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002069 } else {
2070 /*
2071 * If the voice call is active, use the sound devices of voice call usecase
2072 * so that it would not result any device switch. All the usecases will
2073 * be switched to new device when select_devices() is called for voice call
2074 * usecase. This is to avoid switching devices for voice call when
2075 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002076 * choose voice call device only if the use case device is
2077 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002078 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002079 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002080 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002081 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002082 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2083 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302084 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2085 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002086 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002087 in_snd_device = vc_usecase->in_snd_device;
2088 out_snd_device = vc_usecase->out_snd_device;
2089 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002090 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002091 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002092 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002093 if ((voip_usecase != NULL) &&
2094 (usecase->type == PCM_PLAYBACK) &&
2095 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002096 out_snd_device_backend_match = platform_check_backends_match(
2097 voip_usecase->out_snd_device,
2098 platform_get_output_snd_device(
2099 adev->platform,
2100 usecase->stream.out));
2101 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002102 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002103 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2104 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002105 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002106 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002107 in_snd_device = voip_usecase->in_snd_device;
2108 out_snd_device = voip_usecase->out_snd_device;
2109 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002110 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002111 hfp_ucid = audio_extn_hfp_get_usecase();
2112 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002113 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002114 in_snd_device = hfp_usecase->in_snd_device;
2115 out_snd_device = hfp_usecase->out_snd_device;
2116 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002117 }
2118 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302119 if (usecase->stream.out == NULL) {
2120 ALOGE("%s: stream.out is NULL", __func__);
2121 return -EINVAL;
2122 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002123 usecase->devices = usecase->stream.out->devices;
2124 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002125 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002126 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002127 usecase->stream.out);
kunleiz18bdec02018-08-07 17:09:11 +08002128 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2129 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
2130 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2131
2132 if ((usecase->stream.out != NULL &&
2133 voip_usecase != NULL &&
2134 usecase->stream.out->usecase == voip_usecase->id) &&
2135 adev->active_input &&
2136 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
2137 out_snd_device != usecase->out_snd_device) {
2138 select_devices(adev, adev->active_input->usecase);
2139 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002140 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002141 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302142 if (usecase->stream.in == NULL) {
2143 ALOGE("%s: stream.in is NULL", __func__);
2144 return -EINVAL;
2145 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002146 usecase->devices = usecase->stream.in->device;
2147 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002148 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002149 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002150 if (adev->active_input &&
2151 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302152 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleiz18bdec02018-08-07 17:09:11 +08002153 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2154 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2155 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2156 out_device = voip_usecase->stream.out->devices;
2157 else if (adev->primary_output && !adev->primary_output->standby)
2158 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002159 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002160 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2161 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002162 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002163 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002164 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002165 }
2166 }
2167
2168 if (out_snd_device == usecase->out_snd_device &&
2169 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302170
2171 if (!force_device_switch(usecase))
2172 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002173 }
2174
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302175 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
2176 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
2177 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2178 return 0;
2179 }
2180
sangwoobc677242013-08-08 16:53:43 +09002181 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07002182 out_snd_device, platform_get_snd_device_name(out_snd_device),
2183 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002185 /*
2186 * Limitation: While in call, to do a device switch we need to disable
2187 * and enable both RX and TX devices though one of them is same as current
2188 * device.
2189 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002190 if ((usecase->type == VOICE_CALL) &&
2191 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2192 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002193 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002194 }
2195
2196 if (((usecase->type == VOICE_CALL) ||
2197 (usecase->type == VOIP_CALL)) &&
2198 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2199 /* Disable sidetone only if voice/voip call already exists */
2200 if (voice_is_call_state_active(adev) ||
2201 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002202 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002203
2204 /* Disable aanc only if voice call exists */
2205 if (voice_is_call_state_active(adev))
2206 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002207 }
2208
Zhou Songc66eb7e2017-08-08 18:29:07 +08002209 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302210 (!audio_extn_a2dp_is_ready())) {
2211 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002212 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302213 }
2214
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002215 /* Disable current sound devices */
2216 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002217 disable_audio_route(adev, usecase);
2218 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219 }
2220
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002221 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002222 disable_audio_route(adev, usecase);
2223 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002224 }
2225
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002226 /* Applicable only on the targets that has external modem.
2227 * New device information should be sent to modem before enabling
2228 * the devices to reduce in-call device switch time.
2229 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002230 if ((usecase->type == VOICE_CALL) &&
2231 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2232 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002233 status = platform_switch_voice_call_enable_device_config(adev->platform,
2234 out_snd_device,
2235 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002236 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002237
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002238 /* Enable new sound devices */
2239 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002240 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302241 if (platform_check_codec_asrc_support(adev->platform))
2242 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002243 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244 }
2245
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002246 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302247 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002248 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002249 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002250
Avinash Vaish71a8b972014-07-24 15:36:33 +05302251 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002252 status = platform_switch_voice_call_device_post(adev->platform,
2253 out_snd_device,
2254 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302255 enable_audio_route_for_voice_usecases(adev, usecase);
2256 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002257
sangwoo170731f2013-06-08 15:36:36 +09002258 usecase->in_snd_device = in_snd_device;
2259 usecase->out_snd_device = out_snd_device;
2260
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302261 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2262 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302263 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002264 if ((24 == usecase->stream.out->bit_width) &&
2265 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2266 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2267 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2268 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2269 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2270 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2271 /*
2272 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2273 * configured device sample rate, if not update the COPP rate to be equal to the
2274 * device sample rate, else open COPP at stream sample rate
2275 */
2276 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2277 usecase->stream.out->sample_rate,
2278 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302279 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2280 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002281 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2282 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2283 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2284 }
2285
Weiyin Jiang7991be92018-02-01 17:24:33 +08002286 /* Cache stream information to be notified to gef clients */
2287 audio_device = usecase->stream.out->devices;
2288 channel_mask = usecase->stream.out->channel_mask;
2289 sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
2290 acdb_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302291 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002292 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002293
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002294 /* If input stream is already running then effect needs to be
2295 applied on the new input device that's being enabled here. */
2296 if ((in_snd_device != SND_DEVICE_NONE) && (!adev->active_input->standby))
2297 check_and_enable_effect(adev);
2298
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002299 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002300 /* Enable aanc only if voice call exists */
2301 if (voice_is_call_state_active(adev))
2302 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2303
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002304 /* Enable sidetone only if other voice/voip call already exists */
2305 if (voice_is_call_state_active(adev) ||
2306 voice_extn_compress_voip_is_started(adev))
2307 voice_set_sidetone(adev, out_snd_device, true);
2308 }
2309
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002310 /* Applicable only on the targets that has external modem.
2311 * Enable device command should be sent to modem only after
2312 * enabling voice call mixer controls
2313 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002314 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002315 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2316 out_snd_device,
2317 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302318
2319 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2320
2321 if (usecase->type == VOIP_CALL) {
2322 if (adev->active_input != NULL &&
2323 !adev->active_input->standby) {
2324 if (is_bt_soc_on(adev) == false){
2325 ALOGD("BT SCO MIC disconnected while in connection");
2326 if (adev->active_input->pcm != NULL)
2327 pcm_stop(adev->active_input->pcm);
2328 }
2329 }
2330 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2331 && usecase->stream.out->started) {
2332 if (is_bt_soc_on(adev) == false) {
2333 ALOGD("BT SCO/A2DP disconnected while in connection");
2334 out_standby_l(&usecase->stream.out->stream.common);
2335 }
2336 }
2337 } else if ((usecase->stream.out != NULL) &&
2338 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2339 usecase->stream.out->started) {
2340 if (is_bt_soc_on(adev) == false) {
2341 ALOGD("BT SCO/A2dp disconnected while in connection");
2342 out_standby_l(&usecase->stream.out->stream.common);
2343 }
2344 }
2345 }
2346
Weiyin Jiang7991be92018-02-01 17:24:33 +08002347 /* Notify device change info to effect clients registered
2348 * NOTE: device lock has to be unlock temporarily here.
2349 * To the worst case, we notify stale info to clients.
2350 */
2351 if (usecase->type == PCM_PLAYBACK) {
2352 pthread_mutex_unlock(&adev->lock);
2353 audio_extn_gef_notify_device_config(audio_device, channel_mask, sample_rate, acdb_id);
2354 pthread_mutex_lock(&adev->lock);
2355 }
2356
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302357 ALOGD("%s: done",__func__);
2358
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002359 return status;
2360}
2361
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362static int stop_input_stream(struct stream_in *in)
2363{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302364 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002365 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302366
2367 if (in == NULL) {
2368 ALOGE("%s: stream_in ptr is NULL", __func__);
2369 return -EINVAL;
2370 }
2371
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002372 struct audio_device *adev = in->dev;
2373
Eric Laurent994a6932013-07-17 11:51:42 -07002374 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002375 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376 uc_info = get_usecase_from_list(adev, in->usecase);
2377 if (uc_info == NULL) {
2378 ALOGE("%s: Could not find the usecase (%d) in the list",
2379 __func__, in->usecase);
2380 return -EINVAL;
2381 }
2382
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002383 /* Close in-call recording streams */
2384 voice_check_and_stop_incall_rec_usecase(adev, in);
2385
Eric Laurent150dbfe2013-02-27 14:31:02 -08002386 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002387 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002388
2389 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002390 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002391
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002392 list_remove(&uc_info->list);
2393 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002394
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002395 adev->active_input = get_next_active_input(adev);
2396
Eric Laurent994a6932013-07-17 11:51:42 -07002397 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002398 return ret;
2399}
2400
2401int start_input_stream(struct stream_in *in)
2402{
2403 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002404 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002405 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302406
2407 if (in == NULL) {
2408 ALOGE("%s: stream_in ptr is NULL", __func__);
2409 return -EINVAL;
2410 }
2411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002413 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002414 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415
Mingming Yin2664a5b2015-09-03 10:53:11 -07002416 if (get_usecase_from_list(adev, usecase) == NULL)
2417 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302418 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2419 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002420
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302421 if (CARD_STATUS_OFFLINE == in->card_status||
2422 CARD_STATUS_OFFLINE == adev->card_status) {
2423 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302424 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302425 goto error_config;
2426 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302427
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302428 if (audio_is_bluetooth_sco_device(in->device)) {
2429 if (!adev->bt_sco_on) {
2430 ALOGE("%s: SCO profile is not ready, return error", __func__);
2431 ret = -EIO;
2432 goto error_config;
2433 }
2434 }
2435
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002436 /* Check if source matches incall recording usecase criteria */
2437 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2438 if (ret)
2439 goto error_config;
2440 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002441 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2442
2443 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2444 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2445 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002446 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002447 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002448
Eric Laurentb23d5282013-05-14 15:27:20 -07002449 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450 if (in->pcm_device_id < 0) {
2451 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2452 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002453 ret = -EINVAL;
2454 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002456
2457 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002458 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002459
2460 if (!uc_info) {
2461 ret = -ENOMEM;
2462 goto error_config;
2463 }
2464
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465 uc_info->id = in->usecase;
2466 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002467 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002468 uc_info->devices = in->device;
2469 uc_info->in_snd_device = SND_DEVICE_NONE;
2470 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002471
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002472 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302473 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2474 adev->perf_lock_opts,
2475 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002476 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477
Haynes Mathew George16081042017-05-31 17:16:49 -07002478 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302479 ret = audio_extn_cin_start_input_stream(in);
2480 if (ret)
2481 goto error_open;
2482 else
2483 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002484 }
2485
Haynes Mathew George16081042017-05-31 17:16:49 -07002486 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002487 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002488 ALOGE("%s: pcm stream not ready", __func__);
2489 goto error_open;
2490 }
2491 ret = pcm_start(in->pcm);
2492 if (ret < 0) {
2493 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2494 goto error_open;
2495 }
2496 } else {
2497 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2498 unsigned int pcm_open_retry_count = 0;
2499
2500 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2501 flags |= PCM_MMAP | PCM_NOIRQ;
2502 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2503 } else if (in->realtime) {
2504 flags |= PCM_MMAP | PCM_NOIRQ;
2505 }
2506
Garmond Leunge2433c32017-09-28 21:51:22 -07002507 if (audio_extn_ffv_get_stream() == in) {
2508 ALOGD("%s: ffv stream, update pcm config", __func__);
2509 audio_extn_ffv_update_pcm_config(&config);
2510 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002511 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2512 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2513
2514 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002515 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002516 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002517 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002518 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302519 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302520 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2521 adev->card_status = CARD_STATUS_OFFLINE;
2522 in->card_status = CARD_STATUS_OFFLINE;
2523 ret = -EIO;
2524 goto error_open;
2525 }
2526
Haynes Mathew George16081042017-05-31 17:16:49 -07002527 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2528 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2529 if (in->pcm != NULL) {
2530 pcm_close(in->pcm);
2531 in->pcm = NULL;
2532 }
2533 if (pcm_open_retry_count-- == 0) {
2534 ret = -EIO;
2535 goto error_open;
2536 }
2537 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2538 continue;
2539 }
2540 break;
2541 }
2542
2543 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002544 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002545 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002546 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002547 if (ret < 0) {
2548 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2549 pcm_close(in->pcm);
2550 in->pcm = NULL;
2551 goto error_open;
2552 }
2553 register_in_stream(in);
2554 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002555 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002556 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002557 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002558 if (ret < 0) {
2559 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002560 pcm_close(in->pcm);
2561 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002562 goto error_open;
2563 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002564 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002565 }
2566
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002567 check_and_enable_effect(adev);
2568
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302569done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302570 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002571 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002572
Eric Laurentc8400632013-02-14 19:04:54 -08002573 return ret;
2574
2575error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302576 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002578error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302579 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302580 /*
2581 * sleep 50ms to allow sufficient time for kernel
2582 * drivers to recover incases like SSR.
2583 */
2584 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002585 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002586
2587 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002588}
2589
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002590void lock_input_stream(struct stream_in *in)
2591{
2592 pthread_mutex_lock(&in->pre_lock);
2593 pthread_mutex_lock(&in->lock);
2594 pthread_mutex_unlock(&in->pre_lock);
2595}
2596
2597void lock_output_stream(struct stream_out *out)
2598{
2599 pthread_mutex_lock(&out->pre_lock);
2600 pthread_mutex_lock(&out->lock);
2601 pthread_mutex_unlock(&out->pre_lock);
2602}
2603
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002604/* must be called with out->lock locked */
2605static int send_offload_cmd_l(struct stream_out* out, int command)
2606{
2607 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2608
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002609 if (!cmd) {
2610 ALOGE("failed to allocate mem for command 0x%x", command);
2611 return -ENOMEM;
2612 }
2613
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002614 ALOGVV("%s %d", __func__, command);
2615
2616 cmd->cmd = command;
2617 list_add_tail(&out->offload_cmd_list, &cmd->node);
2618 pthread_cond_signal(&out->offload_cond);
2619 return 0;
2620}
2621
2622/* must be called iwth out->lock locked */
2623static void stop_compressed_output_l(struct stream_out *out)
2624{
2625 out->offload_state = OFFLOAD_STATE_IDLE;
2626 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002627 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002628 if (out->compr != NULL) {
2629 compress_stop(out->compr);
2630 while (out->offload_thread_blocked) {
2631 pthread_cond_wait(&out->cond, &out->lock);
2632 }
2633 }
2634}
2635
Varun Balaraje49253e2017-07-06 19:48:56 +05302636bool is_interactive_usecase(audio_usecase_t uc_id)
2637{
2638 unsigned int i;
2639 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2640 if (uc_id == interactive_usecases[i])
2641 return true;
2642 }
2643 return false;
2644}
2645
2646static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2647{
2648 audio_usecase_t ret_uc = USECASE_INVALID;
2649 unsigned int intract_uc_index;
2650 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2651
2652 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2653 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2654 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2655 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2656 ret_uc = interactive_usecases[intract_uc_index];
2657 break;
2658 }
2659 }
2660
2661 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2662 return ret_uc;
2663}
2664
2665static void free_interactive_usecase(struct audio_device *adev,
2666 audio_usecase_t uc_id)
2667{
2668 unsigned int interact_uc_index;
2669 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2670
2671 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2672 if (interactive_usecases[interact_uc_index] == uc_id) {
2673 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2674 break;
2675 }
2676 }
2677 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2678}
2679
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002680bool is_offload_usecase(audio_usecase_t uc_id)
2681{
2682 unsigned int i;
2683 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2684 if (uc_id == offload_usecases[i])
2685 return true;
2686 }
2687 return false;
2688}
2689
Dhananjay Kumarac341582017-02-23 23:42:25 +05302690static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002691{
vivek mehta446c3962015-09-14 10:57:35 -07002692 audio_usecase_t ret_uc = USECASE_INVALID;
2693 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002694 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002695 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302696 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002697 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2698 else
2699 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002700
vivek mehta446c3962015-09-14 10:57:35 -07002701 pthread_mutex_lock(&adev->lock);
2702 if (get_usecase_from_list(adev, ret_uc) != NULL)
2703 ret_uc = USECASE_INVALID;
2704 pthread_mutex_unlock(&adev->lock);
2705
2706 return ret_uc;
2707 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002708
2709 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002710 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2711 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2712 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2713 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002714 break;
2715 }
2716 }
vivek mehta446c3962015-09-14 10:57:35 -07002717
2718 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2719 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002720}
2721
2722static void free_offload_usecase(struct audio_device *adev,
2723 audio_usecase_t uc_id)
2724{
vivek mehta446c3962015-09-14 10:57:35 -07002725 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002726 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002727
2728 if (!adev->multi_offload_enable)
2729 return;
2730
2731 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2732 if (offload_usecases[offload_uc_index] == uc_id) {
2733 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002734 break;
2735 }
2736 }
2737 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2738}
2739
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002740static void *offload_thread_loop(void *context)
2741{
2742 struct stream_out *out = (struct stream_out *) context;
2743 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002744 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002745
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002746 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2747 set_sched_policy(0, SP_FOREGROUND);
2748 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2749
2750 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002751 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002752 for (;;) {
2753 struct offload_cmd *cmd = NULL;
2754 stream_callback_event_t event;
2755 bool send_callback = false;
2756
2757 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2758 __func__, list_empty(&out->offload_cmd_list),
2759 out->offload_state);
2760 if (list_empty(&out->offload_cmd_list)) {
2761 ALOGV("%s SLEEPING", __func__);
2762 pthread_cond_wait(&out->offload_cond, &out->lock);
2763 ALOGV("%s RUNNING", __func__);
2764 continue;
2765 }
2766
2767 item = list_head(&out->offload_cmd_list);
2768 cmd = node_to_item(item, struct offload_cmd, node);
2769 list_remove(item);
2770
2771 ALOGVV("%s STATE %d CMD %d out->compr %p",
2772 __func__, out->offload_state, cmd->cmd, out->compr);
2773
2774 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2775 free(cmd);
2776 break;
2777 }
2778
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002779 // allow OFFLOAD_CMD_ERROR reporting during standby
2780 // this is needed to handle failures during compress_open
2781 // Note however that on a pause timeout, the stream is closed
2782 // and no offload usecase will be active. Therefore this
2783 // special case is needed for compress_open failures alone
2784 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2785 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002786 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002787 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002788 pthread_cond_signal(&out->cond);
2789 continue;
2790 }
2791 out->offload_thread_blocked = true;
2792 pthread_mutex_unlock(&out->lock);
2793 send_callback = false;
2794 switch(cmd->cmd) {
2795 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002796 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002797 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002798 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002799 send_callback = true;
2800 event = STREAM_CBK_EVENT_WRITE_READY;
2801 break;
2802 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002803 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302804 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002805 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302806 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002807 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302808 if (ret < 0)
2809 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302810 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302811 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002812 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002813 else
2814 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002815 if (-ENETRESET != ret && !(-EINTR == ret &&
2816 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302817 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302818 pthread_mutex_lock(&out->lock);
2819 out->send_new_metadata = 1;
2820 out->send_next_track_params = true;
2821 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302822 event = STREAM_CBK_EVENT_DRAIN_READY;
2823 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2824 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302825 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002826 break;
2827 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002828 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002829 ret = compress_drain(out->compr);
2830 ALOGD("copl(%p):out of compress_drain", out);
2831 // EINTR check avoids drain interruption due to SSR
2832 if (-ENETRESET != ret && !(-EINTR == ret &&
2833 CARD_STATUS_OFFLINE == out->card_status)) {
2834 send_callback = true;
2835 event = STREAM_CBK_EVENT_DRAIN_READY;
2836 } else
2837 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002838 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302839 case OFFLOAD_CMD_ERROR:
2840 ALOGD("copl(%p): sending error callback to AF", out);
2841 send_callback = true;
2842 event = STREAM_CBK_EVENT_ERROR;
2843 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002844 default:
2845 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2846 break;
2847 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002848 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002849 out->offload_thread_blocked = false;
2850 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002851 if (send_callback && out->client_callback) {
2852 ALOGVV("%s: sending client_callback event %d", __func__, event);
2853 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002854 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002855 free(cmd);
2856 }
2857
2858 pthread_cond_signal(&out->cond);
2859 while (!list_empty(&out->offload_cmd_list)) {
2860 item = list_head(&out->offload_cmd_list);
2861 list_remove(item);
2862 free(node_to_item(item, struct offload_cmd, node));
2863 }
2864 pthread_mutex_unlock(&out->lock);
2865
2866 return NULL;
2867}
2868
2869static int create_offload_callback_thread(struct stream_out *out)
2870{
2871 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2872 list_init(&out->offload_cmd_list);
2873 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2874 offload_thread_loop, out);
2875 return 0;
2876}
2877
2878static int destroy_offload_callback_thread(struct stream_out *out)
2879{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002880 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002881 stop_compressed_output_l(out);
2882 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2883
2884 pthread_mutex_unlock(&out->lock);
2885 pthread_join(out->offload_thread, (void **) NULL);
2886 pthread_cond_destroy(&out->offload_cond);
2887
2888 return 0;
2889}
2890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891static int stop_output_stream(struct stream_out *out)
2892{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302893 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002894 struct audio_usecase *uc_info;
2895 struct audio_device *adev = out->dev;
2896
Eric Laurent994a6932013-07-17 11:51:42 -07002897 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002898 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002899 uc_info = get_usecase_from_list(adev, out->usecase);
2900 if (uc_info == NULL) {
2901 ALOGE("%s: Could not find the usecase (%d) in the list",
2902 __func__, out->usecase);
2903 return -EINVAL;
2904 }
2905
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002906 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302907 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002908 if (adev->visualizer_stop_output != NULL)
2909 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002910
2911 audio_extn_dts_remove_state_notifier_node(out->usecase);
2912
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002913 if (adev->offload_effects_stop_output != NULL)
2914 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2915 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002916
Eric Laurent150dbfe2013-02-27 14:31:02 -08002917 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002918 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002919
2920 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002921 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002923 if (is_offload_usecase(out->usecase)) {
2924 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2925 adev->dsp_bit_width_enforce_mode,
2926 false);
2927 }
2928
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002929 list_remove(&uc_info->list);
2930 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302931 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002932 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302933 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002934 ALOGV("Disable passthrough , reset mixer to pcm");
2935 /* NO_PASSTHROUGH */
2936 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002937 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002938 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2939 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002940
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302941 /* Must be called after removing the usecase from list */
2942 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05302943 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302944
Manish Dewangan21a850a2017-08-14 12:03:55 +05302945 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002946 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2947 if (ret < 0)
2948 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2949 }
2950
Eric Laurent994a6932013-07-17 11:51:42 -07002951 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002952 return ret;
2953}
2954
2955int start_output_stream(struct stream_out *out)
2956{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002957 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002958 struct audio_usecase *uc_info;
2959 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002960 char mixer_ctl_name[128];
2961 struct mixer_ctl *ctl = NULL;
2962 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302963 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964
Haynes Mathew George380745d2017-10-04 15:27:45 -07002965 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002966 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2967 ret = -EINVAL;
2968 goto error_config;
2969 }
2970
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302971 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2972 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2973 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302974
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302975 if (CARD_STATUS_OFFLINE == out->card_status ||
2976 CARD_STATUS_OFFLINE == adev->card_status) {
2977 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302978 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302979 goto error_config;
2980 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302981
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302982 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2983 if (!audio_extn_a2dp_is_ready()) {
2984 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302985 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302986 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302987 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2988 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2989 ret = -EAGAIN;
2990 goto error_config;
2991 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302992 }
2993 }
2994 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302995 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2996 if (!adev->bt_sco_on) {
2997 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2998 //combo usecase just by pass a2dp
2999 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3000 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3001 } else {
3002 ALOGE("%s: SCO profile is not ready, return error", __func__);
3003 ret = -EAGAIN;
3004 goto error_config;
3005 }
3006 }
3007 }
3008
Eric Laurentb23d5282013-05-14 15:27:20 -07003009 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010 if (out->pcm_device_id < 0) {
3011 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3012 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003013 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003014 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015 }
3016
3017 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003018
3019 if (!uc_info) {
3020 ret = -ENOMEM;
3021 goto error_config;
3022 }
3023
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024 uc_info->id = out->usecase;
3025 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003026 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003027 uc_info->devices = out->devices;
3028 uc_info->in_snd_device = SND_DEVICE_NONE;
3029 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003030 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303032 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3033 adev->perf_lock_opts,
3034 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303035
3036 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303037 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303038 if (audio_extn_passthru_is_enabled() &&
3039 audio_extn_passthru_is_passthrough_stream(out)) {
3040 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303041 }
3042 }
3043
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303044 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3045 (!audio_extn_a2dp_is_ready())) {
3046 if (!a2dp_combo) {
3047 check_a2dp_restore_l(adev, out, false);
3048 } else {
3049 audio_devices_t dev = out->devices;
3050 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3051 select_devices(adev, out->usecase);
3052 out->devices = dev;
3053 }
3054 } else {
3055 select_devices(adev, out->usecase);
3056 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003057
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003058 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3059 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003060
3061 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3062 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3063 ALOGE("%s: pcm stream not ready", __func__);
3064 goto error_open;
3065 }
3066 ret = pcm_start(out->pcm);
3067 if (ret < 0) {
3068 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3069 goto error_open;
3070 }
3071 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003072 unsigned int flags = PCM_OUT;
3073 unsigned int pcm_open_retry_count = 0;
3074 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3075 flags |= PCM_MMAP | PCM_NOIRQ;
3076 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003077 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003078 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003079 } else
3080 flags |= PCM_MONOTONIC;
3081
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003082 if ((adev->vr_audio_mode_enabled) &&
3083 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3084 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3085 "PCM_Dev %d Topology", out->pcm_device_id);
3086 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3087 if (!ctl) {
3088 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3089 __func__, mixer_ctl_name);
3090 } else {
3091 //if success use ULLPP
3092 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3093 __func__, mixer_ctl_name, out->pcm_device_id);
3094 //There is a still a possibility that some sessions
3095 // that request for FAST|RAW when 3D audio is active
3096 //can go through ULLPP. Ideally we expects apps to
3097 //listen to audio focus and stop concurrent playback
3098 //Also, we will look for mode flag (voice_in_communication)
3099 //before enabling the realtime flag.
3100 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3101 }
3102 }
3103
Surendar Karka91fa3682018-07-02 18:12:12 +05303104 if (out->realtime)
3105 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3106 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3107
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003108 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003109 ATRACE_BEGIN("pcm_open");
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003110 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3111 flags, &out->config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003112 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303113 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303114 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3115 out->card_status = CARD_STATUS_OFFLINE;
3116 adev->card_status = CARD_STATUS_OFFLINE;
3117 ret = -EIO;
3118 goto error_open;
3119 }
3120
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003121 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3122 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3123 if (out->pcm != NULL) {
3124 pcm_close(out->pcm);
3125 out->pcm = NULL;
3126 }
3127 if (pcm_open_retry_count-- == 0) {
3128 ret = -EIO;
3129 goto error_open;
3130 }
3131 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3132 continue;
3133 }
3134 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003135 }
Surendar Karka91fa3682018-07-02 18:12:12 +05303136 if (!out->realtime)
3137 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303138 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003139
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003140 ALOGV("%s: pcm_prepare", __func__);
3141 if (pcm_is_ready(out->pcm)) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003142 ATRACE_BEGIN("pcm_prepare");
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003143 ret = pcm_prepare(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003144 ATRACE_END();
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003145 if (ret < 0) {
3146 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3147 pcm_close(out->pcm);
3148 out->pcm = NULL;
3149 goto error_open;
3150 }
3151 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08003152 // apply volume for voip playback after path is set up
3153 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3154 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303155 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) &&
3156 (out->apply_volume)) {
3157 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3158 out->apply_volume = false;
3159 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003160 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003161 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303162 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003163 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3164 adev->dsp_bit_width_enforce_mode,
3165 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003167 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003168 out->compr = compress_open(adev->snd_card,
3169 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003170 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003171 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303172 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303173 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3174 adev->card_status = CARD_STATUS_OFFLINE;
3175 out->card_status = CARD_STATUS_OFFLINE;
3176 ret = -EIO;
3177 goto error_open;
3178 }
3179
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003180 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003181 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003182 compress_close(out->compr);
3183 out->compr = NULL;
3184 ret = -EIO;
3185 goto error_open;
3186 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303187 /* compress_open sends params of the track, so reset the flag here */
3188 out->is_compr_metadata_avail = false;
3189
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003190 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003191 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003192
Fred Oh3f43e742015-03-04 18:42:34 -08003193 /* Since small bufs uses blocking writes, a write will be blocked
3194 for the default max poll time (20s) in the event of an SSR.
3195 Reduce the poll time to observe and deal with SSR faster.
3196 */
Ashish Jain5106d362016-05-11 19:23:33 +05303197 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003198 compress_set_max_poll_wait(out->compr, 1000);
3199 }
3200
Manish Dewangan69426c82017-01-30 17:35:36 +05303201 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303202 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303203
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003204 audio_extn_dts_create_state_notifier_node(out->usecase);
3205 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3206 popcount(out->channel_mask),
3207 out->playback_started);
3208
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003209#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303210 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003211 audio_extn_dolby_send_ddp_endp_params(adev);
3212#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303213 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3214 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003215 if (adev->visualizer_start_output != NULL)
3216 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3217 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303218 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003219 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003220 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003222
3223 if (ret == 0) {
3224 register_out_stream(out);
3225 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003226 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3227 ALOGE("%s: pcm stream not ready", __func__);
3228 goto error_open;
3229 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003230 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003231 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003232 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003233 if (ret < 0)
3234 goto error_open;
3235 }
3236 }
3237
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303238 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003239 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003240
Manish Dewangan21a850a2017-08-14 12:03:55 +05303241 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003242 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003243 if (ret < 0)
3244 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3245 }
3246
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003247 // consider a scenario where on pause lower layers are tear down.
3248 // so on resume, swap mixer control need to be sent only when
3249 // backend is active, hence rather than sending from enable device
3250 // sending it from start of streamtream
3251
3252 platform_set_swap_channels(adev, true);
3253
Haynes Mathew George380745d2017-10-04 15:27:45 -07003254 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003255 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003256error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303257 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003258 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003259error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303260 /*
3261 * sleep 50ms to allow sufficient time for kernel
3262 * drivers to recover incases like SSR.
3263 */
3264 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003265 ATRACE_END();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003266 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003267}
3268
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269static int check_input_parameters(uint32_t sample_rate,
3270 audio_format_t format,
3271 int channel_count)
3272{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003273 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303275 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3276 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3277 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003278 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003279 !audio_extn_compr_cap_format_supported(format) &&
3280 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003281 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003282
3283 switch (channel_count) {
3284 case 1:
3285 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303286 case 3:
3287 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003288 case 6:
Ralf Herzaec80262018-07-03 07:08:49 +02003289 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003290 break;
3291 default:
3292 ret = -EINVAL;
3293 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003294
3295 switch (sample_rate) {
3296 case 8000:
3297 case 11025:
3298 case 12000:
3299 case 16000:
3300 case 22050:
3301 case 24000:
3302 case 32000:
3303 case 44100:
3304 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003305 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303306 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003307 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303308 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309 break;
3310 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003311 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312 }
3313
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003314 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003315}
3316
3317static size_t get_input_buffer_size(uint32_t sample_rate,
3318 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003319 int channel_count,
3320 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321{
Ralf Herzbd08d632018-09-28 15:50:49 +02003322 int i = 0;
3323 size_t frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324 size_t size = 0;
3325
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003326 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3327 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003329 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003330 if (is_low_latency)
3331 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303332
Ralf Herzbd08d632018-09-28 15:50:49 +02003333 frame_size = audio_bytes_per_sample(format) * channel_count;
3334 size *= frame_size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003335
Ralf Herzbd08d632018-09-28 15:50:49 +02003336 /* make sure the size is multiple of 32 bytes and additionally multiple of
3337 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003338 * At 48 kHz mono 16-bit PCM:
3339 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3340 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Ralf Herzbd08d632018-09-28 15:50:49 +02003341 *
3342 * The loop reaches result within 32 iterations, as initial size is
3343 * already a multiple of frame_size
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003344 */
Ralf Herzbd08d632018-09-28 15:50:49 +02003345 for (i=0; i<32; i++) {
3346 if ((size & 0x1f) == 0)
3347 break;
3348 size += frame_size;
3349 }
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003350
3351 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352}
3353
Ashish Jain058165c2016-09-28 23:18:48 +05303354static size_t get_output_period_size(uint32_t sample_rate,
3355 audio_format_t format,
3356 int channel_count,
3357 int duration /*in millisecs*/)
3358{
3359 size_t size = 0;
3360 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3361
3362 if ((duration == 0) || (sample_rate == 0) ||
3363 (bytes_per_sample == 0) || (channel_count == 0)) {
3364 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3365 bytes_per_sample, channel_count);
3366 return -EINVAL;
3367 }
3368
3369 size = (sample_rate *
3370 duration *
3371 bytes_per_sample *
3372 channel_count) / 1000;
3373 /*
3374 * To have same PCM samples for all channels, the buffer size requires to
3375 * be multiple of (number of channels * bytes per sample)
3376 * For writes to succeed, the buffer must be written at address which is multiple of 32
3377 */
3378 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3379
3380 return (size/(channel_count * bytes_per_sample));
3381}
3382
Zhou Song48453a02018-01-10 17:50:59 +08003383static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303384{
3385 uint64_t actual_frames_rendered = 0;
3386 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3387
3388 /* This adjustment accounts for buffering after app processor.
3389 * It is based on estimated DSP latency per use case, rather than exact.
3390 */
3391 int64_t platform_latency = platform_render_latency(out->usecase) *
3392 out->sample_rate / 1000000LL;
3393
Zhou Song48453a02018-01-10 17:50:59 +08003394 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303395 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3396 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3397 * hence only estimate.
3398 */
3399 int64_t signed_frames = out->written - kernel_buffer_size;
3400
3401 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3402
Zhou Song48453a02018-01-10 17:50:59 +08003403 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303404 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003405 if (timestamp != NULL )
3406 *timestamp = out->writeAt;
3407 } else if (timestamp != NULL) {
3408 clock_gettime(CLOCK_MONOTONIC, timestamp);
3409 }
3410 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303411
3412 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3413 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3414 (long long int)out->written, (int)kernel_buffer_size,
3415 audio_bytes_per_sample(out->compr_config.codec->format),
3416 popcount(out->channel_mask));
3417
3418 return actual_frames_rendered;
3419}
3420
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3422{
3423 struct stream_out *out = (struct stream_out *)stream;
3424
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003425 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426}
3427
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003428static int out_set_sample_rate(struct audio_stream *stream __unused,
3429 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003430{
3431 return -ENOSYS;
3432}
3433
3434static size_t out_get_buffer_size(const struct audio_stream *stream)
3435{
3436 struct stream_out *out = (struct stream_out *)stream;
3437
Varun Balaraje49253e2017-07-06 19:48:56 +05303438 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303439 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303440 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303441 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3442 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3443 else
3444 return out->compr_config.fragment_size;
3445 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003446 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003447 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3448 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 +05303449 else if (is_offload_usecase(out->usecase) &&
3450 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303451 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003452
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003453 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003454 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455}
3456
3457static uint32_t out_get_channels(const struct audio_stream *stream)
3458{
3459 struct stream_out *out = (struct stream_out *)stream;
3460
3461 return out->channel_mask;
3462}
3463
3464static audio_format_t out_get_format(const struct audio_stream *stream)
3465{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003466 struct stream_out *out = (struct stream_out *)stream;
3467
3468 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469}
3470
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003471static int out_set_format(struct audio_stream *stream __unused,
3472 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003473{
3474 return -ENOSYS;
3475}
3476
3477static int out_standby(struct audio_stream *stream)
3478{
3479 struct stream_out *out = (struct stream_out *)stream;
3480 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003481 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003482
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303483 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3484 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003486 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003487 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003488 if (adev->adm_deregister_stream)
3489 adev->adm_deregister_stream(adev->adm_data, out->handle);
3490
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003491 if (is_offload_usecase(out->usecase))
3492 stop_compressed_output_l(out);
3493
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003494 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003496 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3497 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303498 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003499 pthread_mutex_unlock(&adev->lock);
3500 pthread_mutex_unlock(&out->lock);
3501 ALOGD("VOIP output entered standby");
3502 return 0;
3503 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003504 if (out->pcm) {
3505 pcm_close(out->pcm);
3506 out->pcm = NULL;
3507 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003508 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3509 do_stop = out->playback_started;
3510 out->playback_started = false;
3511 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003512 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003513 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303514 out->send_next_track_params = false;
3515 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003516 out->gapless_mdata.encoder_delay = 0;
3517 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003518 if (out->compr != NULL) {
3519 compress_close(out->compr);
3520 out->compr = NULL;
3521 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003522 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003523 if (do_stop) {
3524 stop_output_stream(out);
3525 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003526 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527 }
3528 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303529 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530 return 0;
3531}
3532
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303533static int out_on_error(struct audio_stream *stream)
3534{
3535 struct stream_out *out = (struct stream_out *)stream;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303536
3537 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003538 // always send CMD_ERROR for offload streams, this
3539 // is needed e.g. when SSR happens within compress_open
3540 // since the stream is active, offload_callback_thread is also active.
3541 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3542 stop_compressed_output_l(out);
3543 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303544 }
3545 pthread_mutex_unlock(&out->lock);
3546
Aniket Kumar Lata28abfc12017-12-28 10:53:07 -08003547 return out_standby(&out->stream.common);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303548}
3549
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303550/*
3551 *standby implementation without locks, assumes that the callee already
3552 *has taken adev and out lock.
3553 */
3554int out_standby_l(struct audio_stream *stream)
3555{
3556 struct stream_out *out = (struct stream_out *)stream;
3557 struct audio_device *adev = out->dev;
3558
3559 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3560 stream, out->usecase, use_case_table[out->usecase]);
3561
3562 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003563 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303564 if (adev->adm_deregister_stream)
3565 adev->adm_deregister_stream(adev->adm_data, out->handle);
3566
3567 if (is_offload_usecase(out->usecase))
3568 stop_compressed_output_l(out);
3569
3570 out->standby = true;
3571 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3572 voice_extn_compress_voip_close_output_stream(stream);
3573 out->started = 0;
3574 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003575 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303576 return 0;
3577 } else if (!is_offload_usecase(out->usecase)) {
3578 if (out->pcm) {
3579 pcm_close(out->pcm);
3580 out->pcm = NULL;
3581 }
3582 } else {
3583 ALOGD("copl(%p):standby", out);
3584 out->send_next_track_params = false;
3585 out->is_compr_metadata_avail = false;
3586 out->gapless_mdata.encoder_delay = 0;
3587 out->gapless_mdata.encoder_padding = 0;
3588 if (out->compr != NULL) {
3589 compress_close(out->compr);
3590 out->compr = NULL;
3591 }
3592 }
3593 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003594 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303595 }
3596 ALOGD("%s: exit", __func__);
3597 return 0;
3598}
3599
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003600static int out_dump(const struct audio_stream *stream __unused,
3601 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003602{
3603 return 0;
3604}
3605
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003606static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3607{
3608 int ret = 0;
3609 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003610
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003611 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003612 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003613 return -EINVAL;
3614 }
3615
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303616 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003617
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003618 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3619 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303620 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003621 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003622 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3623 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303624 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003625 }
3626
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003627 ALOGV("%s new encoder delay %u and padding %u", __func__,
3628 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3629
3630 return 0;
3631}
3632
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003633static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3634{
3635 return out == adev->primary_output || out == adev->voice_tx_output;
3636}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003637
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303638// note: this call is safe only if the stream_cb is
3639// removed first in close_output_stream (as is done now).
3640static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3641{
3642 if (!stream || !parms)
3643 return;
3644
3645 struct stream_out *out = (struct stream_out *)stream;
3646 struct audio_device *adev = out->dev;
3647
3648 card_status_t status;
3649 int card;
3650 if (parse_snd_card_status(parms, &card, &status) < 0)
3651 return;
3652
3653 pthread_mutex_lock(&adev->lock);
3654 bool valid_cb = (card == adev->snd_card);
3655 pthread_mutex_unlock(&adev->lock);
3656
3657 if (!valid_cb)
3658 return;
3659
3660 lock_output_stream(out);
3661 if (out->card_status != status)
3662 out->card_status = status;
3663 pthread_mutex_unlock(&out->lock);
3664
3665 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3666 use_case_table[out->usecase],
3667 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3668
3669 if (status == CARD_STATUS_OFFLINE)
3670 out_on_error(stream);
3671
3672 return;
3673}
3674
Kevin Rocardfce19002017-08-07 19:21:36 -07003675static int get_alive_usb_card(struct str_parms* parms) {
3676 int card;
3677 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
3678 !audio_extn_usb_alive(card)) {
3679 return card;
3680 }
3681 return -ENODEV;
3682}
3683
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3685{
3686 struct stream_out *out = (struct stream_out *)stream;
3687 struct audio_device *adev = out->dev;
3688 struct str_parms *parms;
3689 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003690 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303691 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692
sangwoobc677242013-08-08 16:53:43 +09003693 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003694 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003695 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303696 if (!parms)
3697 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003698 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3699 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003701 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003702 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003704 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003705 * When HDMI cable is unplugged the music playback is paused and
3706 * the policy manager sends routing=0. But the audioflinger continues
3707 * to write data until standby time (3sec). As the HDMI core is
3708 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003709 * Avoid this by routing audio to speaker until standby.
3710 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003711 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3712 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303713 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003714 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3715 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003716 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303717 /*
3718 * When A2DP is disconnected the
3719 * music playback is paused and the policy manager sends routing=0
3720 * But the audioflingercontinues to write data until standby time
3721 * (3sec). As BT is turned off, the write gets blocked.
3722 * Avoid this by routing audio to speaker until standby.
3723 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003724 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07003725 (val == AUDIO_DEVICE_NONE) &&
3726 !audio_extn_a2dp_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303727 val = AUDIO_DEVICE_OUT_SPEAKER;
3728 }
Sharad Sangle67d9e7c2018-04-05 23:28:32 +05303729 /*
3730 * When USB headset is disconnected the music platback paused
3731 * and the policy manager send routing=0. But if the USB is connected
3732 * back before the standby time, AFE is not closed and opened
3733 * when USB is connected back. So routing to speker will guarantee
3734 * AFE reconfiguration and AFE will be opend once USB is connected again
3735 */
3736 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
3737 (val == AUDIO_DEVICE_NONE) &&
3738 !audio_extn_usb_connected(parms)) {
3739 val = AUDIO_DEVICE_OUT_SPEAKER;
3740 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303741 /* To avoid a2dp to sco overlapping / BT device improper state
3742 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303743 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303744 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3745 if (!audio_extn_a2dp_is_ready()) {
3746 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3747 //combo usecase just by pass a2dp
3748 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303749 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303750 } else {
3751 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3752 /* update device to a2dp and don't route as BT returned error
3753 * However it is still possible a2dp routing called because
3754 * of current active device disconnection (like wired headset)
3755 */
3756 out->devices = val;
3757 pthread_mutex_unlock(&out->lock);
3758 pthread_mutex_unlock(&adev->lock);
3759 goto error;
3760 }
3761 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303762 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003763
3764 audio_devices_t new_dev = val;
3765
3766 // Workaround: If routing to an non existing usb device, fail gracefully
3767 // The routing request will otherwise block during 10 second
3768 int card;
3769 if (audio_is_usb_out_device(new_dev) &&
3770 (card = get_alive_usb_card(parms)) >= 0) {
3771
3772 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
3773 pthread_mutex_unlock(&adev->lock);
3774 pthread_mutex_unlock(&out->lock);
3775 ret = -ENOSYS;
3776 goto routing_fail;
3777 }
3778
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003779 /*
3780 * select_devices() call below switches all the usecases on the same
3781 * backend to the new device. Refer to check_usecases_codec_backend() in
3782 * the select_devices(). But how do we undo this?
3783 *
3784 * For example, music playback is active on headset (deep-buffer usecase)
3785 * and if we go to ringtones and select a ringtone, low-latency usecase
3786 * will be started on headset+speaker. As we can't enable headset+speaker
3787 * and headset devices at the same time, select_devices() switches the music
3788 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3789 * So when the ringtone playback is completed, how do we undo the same?
3790 *
3791 * We are relying on the out_set_parameters() call on deep-buffer output,
3792 * once the ringtone playback is ended.
3793 * NOTE: We should not check if the current devices are same as new devices.
3794 * Because select_devices() must be called to switch back the music
3795 * playback to headset.
3796 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003797 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003798 audio_devices_t new_dev = val;
3799 bool same_dev = out->devices == new_dev;
3800 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003801
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003802 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08003803 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003804 if (adev->mode == AUDIO_MODE_IN_CALL) {
3805 adev->current_call_output = out;
3806 ret = voice_start_call(adev);
3807 }
3808 } else {
3809 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003810 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003811 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003812 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003813
3814 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003815 if (!same_dev) {
3816 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303817 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3818 adev->perf_lock_opts,
3819 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003820 if (adev->adm_on_routing_change)
3821 adev->adm_on_routing_change(adev->adm_data,
3822 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003823 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303824 if (!bypass_a2dp) {
3825 select_devices(adev, out->usecase);
3826 } else {
3827 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3828 select_devices(adev, out->usecase);
3829 out->devices = new_dev;
3830 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003831
3832 if (!same_dev) {
3833 // on device switch force swap, lower functions will make sure
3834 // to check if swap is allowed or not.
3835 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05303836 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003837 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303838 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3839 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003840 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303841 pthread_mutex_lock(&out->compr_mute_lock);
3842 out->a2dp_compress_mute = false;
3843 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3844 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08003845 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
3846 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303847 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003848 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003849 }
3850
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003851 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003852 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003854 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003855
3856 if (out == adev->primary_output) {
3857 pthread_mutex_lock(&adev->lock);
3858 audio_extn_set_parameters(adev, parms);
3859 pthread_mutex_unlock(&adev->lock);
3860 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003861 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003862 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003863 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003864
3865 audio_extn_dts_create_state_notifier_node(out->usecase);
3866 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3867 popcount(out->channel_mask),
3868 out->playback_started);
3869
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003870 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003871 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003872
Surendar Karkaf51b5842018-04-26 11:28:38 +05303873 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
3874 sizeof(value));
3875 if (err >= 0) {
3876 if (!strncmp("true", value, sizeof("true")) || atoi(value))
3877 audio_extn_send_dual_mono_mixing_coefficients(out);
3878 }
3879
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303880 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3881 if (err >= 0) {
3882 strlcpy(out->profile, value, sizeof(out->profile));
3883 ALOGV("updating stream profile with value '%s'", out->profile);
3884 lock_output_stream(out);
3885 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3886 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07003887 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303888 out->sample_rate, out->bit_width,
3889 out->channel_mask, out->profile,
3890 &out->app_type_cfg);
3891 pthread_mutex_unlock(&out->lock);
3892 }
3893
Alexy Joseph98988832017-01-13 14:56:59 -08003894 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08003895 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
3896 // and vendor.audio.hal.output.suspend.supported is set to true
3897 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08003898 //check suspend parameter only for low latency and if the property
3899 //is enabled
3900 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3901 ALOGI("%s: got suspend_playback %s", __func__, value);
3902 lock_output_stream(out);
3903 if (!strncmp(value, "false", 5)) {
3904 //suspend_playback=false is supposed to set QOS value back to 75%
3905 //the mixer control sent with value Enable will achieve that
3906 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3907 } else if (!strncmp (value, "true", 4)) {
3908 //suspend_playback=true is supposed to remove QOS value
3909 //resetting the mixer control will set the default value
3910 //for the mixer control which is Disable and this removes the QOS vote
3911 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3912 } else {
3913 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3914 " got %s", __func__, value);
3915 ret = -1;
3916 }
3917
3918 if (ret != 0) {
3919 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3920 __func__, out->pm_qos_mixer_path, ret);
3921 }
3922
3923 pthread_mutex_unlock(&out->lock);
3924 }
3925 }
3926 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003927 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303928error:
Eric Laurent994a6932013-07-17 11:51:42 -07003929 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930 return ret;
3931}
3932
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003933static bool stream_get_parameter_channels(struct str_parms *query,
3934 struct str_parms *reply,
3935 audio_channel_mask_t *supported_channel_masks) {
3936 int ret = -1;
3937 char value[512];
3938 bool first = true;
3939 size_t i, j;
3940
3941 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3942 ret = 0;
3943 value[0] = '\0';
3944 i = 0;
3945 while (supported_channel_masks[i] != 0) {
3946 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3947 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
3948 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303949 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003950
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303951 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003952 first = false;
3953 break;
3954 }
3955 }
3956 i++;
3957 }
3958 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3959 }
3960 return ret == 0;
3961}
3962
3963static bool stream_get_parameter_formats(struct str_parms *query,
3964 struct str_parms *reply,
3965 audio_format_t *supported_formats) {
3966 int ret = -1;
3967 char value[256];
3968 size_t i, j;
3969 bool first = true;
3970
3971 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
3972 ret = 0;
3973 value[0] = '\0';
3974 i = 0;
3975 while (supported_formats[i] != 0) {
3976 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
3977 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
3978 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303979 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003980 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303981 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003982 first = false;
3983 break;
3984 }
3985 }
3986 i++;
3987 }
3988 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
3989 }
3990 return ret == 0;
3991}
3992
3993static bool stream_get_parameter_rates(struct str_parms *query,
3994 struct str_parms *reply,
3995 uint32_t *supported_sample_rates) {
3996
3997 int i;
3998 char value[256];
3999 int ret = -1;
4000 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4001 ret = 0;
4002 value[0] = '\0';
4003 i=0;
4004 int cursor = 0;
4005 while (supported_sample_rates[i]) {
4006 int avail = sizeof(value) - cursor;
4007 ret = snprintf(value + cursor, avail, "%s%d",
4008 cursor > 0 ? "|" : "",
4009 supported_sample_rates[i]);
4010 if (ret < 0 || ret >= avail) {
4011 // if cursor is at the last element of the array
4012 // overwrite with \0 is duplicate work as
4013 // snprintf already put a \0 in place.
4014 // else
4015 // we had space to write the '|' at value[cursor]
4016 // (which will be overwritten) or no space to fill
4017 // the first element (=> cursor == 0)
4018 value[cursor] = '\0';
4019 break;
4020 }
4021 cursor += ret;
4022 ++i;
4023 }
4024 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4025 value);
4026 }
4027 return ret >= 0;
4028}
4029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004030static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4031{
4032 struct stream_out *out = (struct stream_out *)stream;
4033 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004034 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004035 char value[256];
4036 struct str_parms *reply = str_parms_create();
4037 size_t i, j;
4038 int ret;
4039 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004040
4041 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004042 if (reply) {
4043 str_parms_destroy(reply);
4044 }
4045 if (query) {
4046 str_parms_destroy(query);
4047 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004048 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4049 return NULL;
4050 }
4051
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004052 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004053 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4054 if (ret >= 0) {
4055 value[0] = '\0';
4056 i = 0;
4057 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004058 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4059 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004061 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004062 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004063 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004064 first = false;
4065 break;
4066 }
4067 }
4068 i++;
4069 }
4070 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4071 str = str_parms_to_str(reply);
4072 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004073 voice_extn_out_get_parameters(out, query, reply);
4074 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004075 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004076
Alexy Joseph62142aa2015-11-16 15:10:34 -08004077
4078 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4079 if (ret >= 0) {
4080 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304081 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4082 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004083 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304084 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004085 } else {
4086 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304087 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004088 }
4089 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004090 if (str)
4091 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004092 str = str_parms_to_str(reply);
4093 }
4094
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004095 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4096 if (ret >= 0) {
4097 value[0] = '\0';
4098 i = 0;
4099 first = true;
4100 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004101 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4102 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004103 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004104 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004105 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004106 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004107 first = false;
4108 break;
4109 }
4110 }
4111 i++;
4112 }
4113 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004114 if (str)
4115 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004116 str = str_parms_to_str(reply);
4117 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004118
4119 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4120 if (ret >= 0) {
4121 value[0] = '\0';
4122 i = 0;
4123 first = true;
4124 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004125 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4126 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004127 if (!first) {
4128 strlcat(value, "|", sizeof(value));
4129 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004130 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004131 first = false;
4132 break;
4133 }
4134 }
4135 i++;
4136 }
4137 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4138 if (str)
4139 free(str);
4140 str = str_parms_to_str(reply);
4141 }
4142
Alexy Joseph98988832017-01-13 14:56:59 -08004143 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4144 //only low latency track supports suspend_resume
4145 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004146 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004147 if (str)
4148 free(str);
4149 str = str_parms_to_str(reply);
4150 }
4151
4152
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004153 str_parms_destroy(query);
4154 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004155 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156 return str;
4157}
4158
4159static uint32_t out_get_latency(const struct audio_stream_out *stream)
4160{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004161 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004163 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004164
Alexy Josephaa54c872014-12-03 02:46:47 -08004165 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304166 lock_output_stream(out);
4167 latency = audio_extn_utils_compress_get_dsp_latency(out);
4168 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004169 } else if ((out->realtime) ||
4170 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004171 // since the buffer won't be filled up faster than realtime,
4172 // return a smaller number
4173 if (out->config.rate)
4174 period_ms = (out->af_period_multiplier * out->config.period_size *
4175 1000) / (out->config.rate);
4176 else
4177 period_ms = 0;
4178 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004179 } else {
4180 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004181 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004182 }
4183
yidongh0515e042017-07-06 15:00:34 +08004184 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004185 latency += audio_extn_a2dp_get_encoder_latency();
4186
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304187 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004188 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004189}
4190
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304191static float AmpToDb(float amplification)
4192{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304193 float db = DSD_VOLUME_MIN_DB;
4194 if (amplification > 0) {
4195 db = 20 * log10(amplification);
4196 if(db < DSD_VOLUME_MIN_DB)
4197 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304198 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304199 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304200}
4201
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304202static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4203 float right)
4204{
4205 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304206 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304207 char mixer_ctl_name[128];
4208 struct audio_device *adev = out->dev;
4209 struct mixer_ctl *ctl;
4210 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4211 PCM_PLAYBACK);
4212
4213 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4214 "Compress Playback %d Volume", pcm_device_id);
4215 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4216 if (!ctl) {
4217 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4218 __func__, mixer_ctl_name);
4219 return -EINVAL;
4220 }
4221 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4222 __func__, mixer_ctl_name, left, right);
4223 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4224 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4225 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4226
4227 return 0;
4228}
4229
Zhou Song2b8f28f2017-09-11 10:51:38 +08004230static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4231 float right)
4232{
4233 struct stream_out *out = (struct stream_out *)stream;
4234 char mixer_ctl_name[] = "App Type Gain";
4235 struct audio_device *adev = out->dev;
4236 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304237 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004238
4239 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4240 if (!ctl) {
4241 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4242 __func__, mixer_ctl_name);
4243 return -EINVAL;
4244 }
4245
4246 set_values[0] = 0; //0: Rx Session 1:Tx Session
4247 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304248 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4249 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004250
4251 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4252 return 0;
4253}
4254
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304255static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
4256 float right)
4257{
4258 struct stream_out *out = (struct stream_out *)stream;
4259 /* Volume control for pcm playback */
4260 if (left != right) {
4261 return -EINVAL;
4262 } else {
4263 char mixer_ctl_name[128];
4264 struct audio_device *adev = out->dev;
4265 struct mixer_ctl *ctl;
4266 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4267 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
4268 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4269 if (!ctl) {
4270 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
4271 return -EINVAL;
4272 }
4273
4274 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
4275 int ret = mixer_ctl_set_value(ctl, 0, volume);
4276 if (ret < 0) {
4277 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
4278 return -EINVAL;
4279 }
4280
4281 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
4282
4283 return 0;
4284 }
4285}
4286
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004287static int out_set_volume(struct audio_stream_out *stream, float left,
4288 float right)
4289{
Eric Laurenta9024de2013-04-04 09:19:12 -07004290 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004291 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304292 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004293
Eric Laurenta9024de2013-04-04 09:19:12 -07004294 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4295 /* only take left channel into account: the API is for stereo anyway */
4296 out->muted = (left == 0.0f);
4297 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004298 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304299 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004300 /*
4301 * Set mute or umute on HDMI passthrough stream.
4302 * Only take left channel into account.
4303 * Mute is 0 and unmute 1
4304 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304305 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304306 } else if (out->format == AUDIO_FORMAT_DSD){
4307 char mixer_ctl_name[128] = "DSD Volume";
4308 struct audio_device *adev = out->dev;
4309 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4310
4311 if (!ctl) {
4312 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4313 __func__, mixer_ctl_name);
4314 return -EINVAL;
4315 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304316 volume[0] = (long)(AmpToDb(left));
4317 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304318 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4319 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004320 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304321 pthread_mutex_lock(&out->compr_mute_lock);
4322 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
4323 if (!out->a2dp_compress_mute)
4324 ret = out_set_compr_volume(stream, left, right);
4325 out->volume_l = left;
4326 out->volume_r = right;
4327 pthread_mutex_unlock(&out->compr_mute_lock);
4328 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004329 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004330 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004331 if (!out->standby)
4332 ret = out_set_voip_volume(stream, left, right);
4333 out->volume_l = left;
4334 out->volume_r = right;
4335 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304336 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
4337 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) {
4338 /* Volume control for pcm playback */
4339 if (!out->standby)
4340 ret = out_set_pcm_volume(stream, left, right);
4341 else
4342 out->apply_volume = true;
4343
4344 out->volume_l = left;
4345 out->volume_r = right;
4346 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004347 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004348
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004349 return -ENOSYS;
4350}
4351
Zhou Songc9672822017-08-16 16:01:39 +08004352static void update_frames_written(struct stream_out *out, size_t bytes)
4353{
4354 size_t bpf = 0;
4355
4356 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4357 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4358 bpf = 1;
4359 else if (!is_offload_usecase(out->usecase))
4360 bpf = audio_bytes_per_sample(out->format) *
4361 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004362
4363 pthread_mutex_lock(&out->position_query_lock);
4364 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004365 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004366 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4367 }
4368 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004369}
4370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004371static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4372 size_t bytes)
4373{
4374 struct stream_out *out = (struct stream_out *)stream;
4375 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004376 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304377 int channels = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004378
Haynes Mathew George380745d2017-10-04 15:27:45 -07004379 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004380 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304381
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304382 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004383
Dhananjay Kumarac341582017-02-23 23:42:25 +05304384 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304385 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304386 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4387 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004388 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304389 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304390 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304391 ALOGD(" %s: sound card is not active/SSR state", __func__);
4392 ret= -EIO;
4393 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304394 }
4395 }
4396
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304397 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304398 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304399 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304400 goto exit;
4401 }
4402
Haynes Mathew George16081042017-05-31 17:16:49 -07004403 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4404 ret = -EINVAL;
4405 goto exit;
4406 }
4407
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304408 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4409 !out->is_iec61937_info_available) {
4410
4411 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4412 out->is_iec61937_info_available = true;
4413 } else if (audio_extn_passthru_is_enabled()) {
4414 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304415 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304416
4417 if((out->format == AUDIO_FORMAT_DTS) ||
4418 (out->format == AUDIO_FORMAT_DTS_HD)) {
4419 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4420 buffer, bytes);
4421 if (ret) {
4422 if (ret != -ENOSYS) {
4423 out->is_iec61937_info_available = false;
4424 ALOGD("iec61937 transmission info not yet updated retry");
4425 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304426 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304427 /* if stream has started and after that there is
4428 * stream config change (iec transmission config)
4429 * then trigger select_device to update backend configuration.
4430 */
4431 out->stream_config_changed = true;
4432 pthread_mutex_lock(&adev->lock);
4433 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304434 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4435 ret = -EINVAL;
4436 goto exit;
4437 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304438 pthread_mutex_unlock(&adev->lock);
4439 out->stream_config_changed = false;
4440 out->is_iec61937_info_available = true;
4441 }
4442 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304443
Garmond Leung317cbf12017-09-13 16:20:50 -07004444 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304445 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4446 (out->is_iec61937_info_available == true)) {
4447 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4448 ret = -EINVAL;
4449 goto exit;
4450 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304451 }
4452 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304453
4454 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4455 (audio_extn_a2dp_is_suspended())) {
4456 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4457 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304458 ret = -EIO;
4459 goto exit;
4460 }
4461 }
4462 }
4463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004464 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004465 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004466 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004467 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4468 ret = voice_extn_compress_voip_start_output_stream(out);
4469 else
4470 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004471 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004472 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004473 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004474 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004475 goto exit;
4476 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304477 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004478 if (last_known_cal_step != -1) {
4479 ALOGD("%s: retry previous failed cal level set", __func__);
4480 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304481 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004482 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304483
4484 if ((out->is_iec61937_info_available == true) &&
4485 (audio_extn_passthru_is_passthrough_stream(out))&&
4486 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4487 ret = -EINVAL;
4488 goto exit;
4489 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05304490 if (out->set_dual_mono)
4491 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004492 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004493
Ashish Jain81eb2a82015-05-13 10:52:34 +05304494 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004495 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304496 adev->is_channel_status_set = true;
4497 }
4498
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004499 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004500 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004501 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004502 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004503 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4504 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304505 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4506 ALOGD("copl(%p):send next track params in gapless", out);
4507 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4508 out->send_next_track_params = false;
4509 out->is_compr_metadata_avail = false;
4510 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004511 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304512 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304513 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004514
Ashish Jain83a6cc22016-06-28 14:34:17 +05304515 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304516 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304517 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304518 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004519 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304520 return -EINVAL;
4521 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304522 audio_format_t dst_format = out->hal_op_format;
4523 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304524
Dieter Luecking5d57def2018-09-07 14:23:37 +02004525 /* prevent division-by-zero */
4526 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
4527 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
4528 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
4529 ALOGE("%s: Error bitwidth == 0", __func__);
4530 ATRACE_END();
4531 return -EINVAL;
4532 }
4533
Ashish Jainf1eaa582016-05-23 20:54:24 +05304534 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4535 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4536
Ashish Jain83a6cc22016-06-28 14:34:17 +05304537 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304538 dst_format,
4539 buffer,
4540 src_format,
4541 frames);
4542
Ashish Jain83a6cc22016-06-28 14:34:17 +05304543 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304544 bytes_to_write);
4545
4546 /*Convert written bytes in audio flinger format*/
4547 if (ret > 0)
4548 ret = ((ret * format_to_bitwidth_table[out->format]) /
4549 format_to_bitwidth_table[dst_format]);
4550 }
4551 } else
4552 ret = compress_write(out->compr, buffer, bytes);
4553
Zhou Songc9672822017-08-16 16:01:39 +08004554 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4555 update_frames_written(out, bytes);
4556
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304557 if (ret < 0)
4558 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304559 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304560 /*msg to cb thread only if non blocking write is enabled*/
4561 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304562 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004563 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304564 } else if (-ENETRESET == ret) {
4565 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304566 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304567 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304568 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004569 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304570 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004571 }
Ashish Jain5106d362016-05-11 19:23:33 +05304572
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304573 /* Call compr start only when non-zero bytes of data is there to be rendered */
4574 if (!out->playback_started && ret > 0) {
4575 int status = compress_start(out->compr);
4576 if (status < 0) {
4577 ret = status;
4578 ALOGE("%s: compr start failed with err %d", __func__, errno);
4579 goto exit;
4580 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004581 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004582 out->playback_started = 1;
4583 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004584
4585 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4586 popcount(out->channel_mask),
4587 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004588 }
4589 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004590 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004591 return ret;
4592 } else {
4593 if (out->pcm) {
4594 if (out->muted)
4595 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004596
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304597 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004598
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004599 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004600
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004601 if (out->config.rate)
4602 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4603 out->config.rate;
4604
4605 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4606
4607 request_out_focus(out, ns);
4608
4609 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004610 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004611 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304612 out->convert_buffer != NULL) {
4613
4614 memcpy_by_audio_format(out->convert_buffer,
4615 out->hal_op_format,
4616 buffer,
4617 out->hal_ip_format,
4618 out->config.period_size * out->config.channels);
4619
4620 ret = pcm_write(out->pcm, out->convert_buffer,
4621 (out->config.period_size *
4622 out->config.channels *
4623 format_to_bitwidth_table[out->hal_op_format]));
4624 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304625 /*
4626 * To avoid underrun in DSP when the application is not pumping
4627 * data at required rate, check for the no. of bytes and ignore
4628 * pcm_write if it is less than actual buffer size.
4629 * It is a work around to a change in compress VOIP driver.
4630 */
4631 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4632 bytes < (out->config.period_size * out->config.channels *
4633 audio_bytes_per_sample(out->format))) {
4634 size_t voip_buf_size =
4635 out->config.period_size * out->config.channels *
4636 audio_bytes_per_sample(out->format);
4637 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4638 __func__, bytes, voip_buf_size);
4639 usleep(((uint64_t)voip_buf_size - bytes) *
4640 1000000 / audio_stream_out_frame_size(stream) /
4641 out_get_sample_rate(&out->stream.common));
4642 ret = 0;
4643 } else
4644 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304645 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004646
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004647 release_out_focus(out);
4648
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304649 if (ret < 0)
4650 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004651 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304652 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004653 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654 }
4655
4656exit:
Zhou Songc9672822017-08-16 16:01:39 +08004657 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304658 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304659 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304660 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004661 pthread_mutex_unlock(&out->lock);
4662
4663 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004664 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004665 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304666 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304667 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304668 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304669 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304670 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304671 out->standby = true;
4672 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304673 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02004674 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
4675 /* prevent division-by-zero */
4676 uint32_t stream_size = audio_stream_out_frame_size(stream);
4677 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004678
Dieter Luecking5d57def2018-09-07 14:23:37 +02004679 if ((stream_size == 0) || (srate == 0)) {
4680 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
4681 ATRACE_END();
4682 return -EINVAL;
4683 }
4684 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
4685 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004686 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mohd Mujahid Pashaa6e89492018-04-09 17:49:11 +05304687 ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004688 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004689 return ret;
4690 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004691 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004692 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693 return bytes;
4694}
4695
4696static int out_get_render_position(const struct audio_stream_out *stream,
4697 uint32_t *dsp_frames)
4698{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004699 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004700
4701 if (dsp_frames == NULL)
4702 return -EINVAL;
4703
4704 *dsp_frames = 0;
4705 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004706 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304707
4708 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4709 * this operation and adev_close_output_stream(where out gets reset).
4710 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304711 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004712 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05304713 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004714 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304715 return 0;
4716 }
4717
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004718 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304719 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304720 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004721 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304722 if (ret < 0)
4723 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004724 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304725 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004726 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304727 if (-ENETRESET == ret) {
4728 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304729 out->card_status = CARD_STATUS_OFFLINE;
4730 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304731 } else if(ret < 0) {
4732 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304733 ret = -EINVAL;
4734 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304735 /*
4736 * Handle corner case where compress session is closed during SSR
4737 * and timestamp is queried
4738 */
4739 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304740 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304741 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304742 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004743 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05304744 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304745 pthread_mutex_unlock(&out->lock);
4746 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004747 } else if (audio_is_linear_pcm(out->format)) {
4748 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004749 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08004750 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004751 } else
4752 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004753}
4754
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004755static int out_add_audio_effect(const struct audio_stream *stream __unused,
4756 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004757{
4758 return 0;
4759}
4760
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004761static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4762 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004763{
4764 return 0;
4765}
4766
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004767static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4768 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004769{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304770 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004771}
4772
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004773static int out_get_presentation_position(const struct audio_stream_out *stream,
4774 uint64_t *frames, struct timespec *timestamp)
4775{
4776 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05304777 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07004778 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004779
Ashish Jain5106d362016-05-11 19:23:33 +05304780 /* below piece of code is not guarded against any lock because audioFliner serializes
4781 * this operation and adev_close_output_stream( where out gets reset).
4782 */
4783 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304784 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004785 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05304786 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4787 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4788 return 0;
4789 }
4790
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004791 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004792
Ashish Jain5106d362016-05-11 19:23:33 +05304793 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4794 ret = compress_get_tstamp(out->compr, &dsp_frames,
4795 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004796 // Adjustment accounts for A2dp encoder latency with offload usecases
4797 // Note: Encoder latency is returned in ms.
4798 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4799 unsigned long offset =
4800 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4801 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4802 }
Ashish Jain5106d362016-05-11 19:23:33 +05304803 ALOGVV("%s rendered frames %ld sample_rate %d",
4804 __func__, dsp_frames, out->sample_rate);
4805 *frames = dsp_frames;
4806 if (ret < 0)
4807 ret = -errno;
4808 if (-ENETRESET == ret) {
4809 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304810 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304811 ret = -EINVAL;
4812 } else
4813 ret = 0;
4814 /* this is the best we can do */
4815 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07004816 } else {
4817 if (out->pcm) {
Weiyin Jiang2da27362018-03-16 12:05:03 +08004818 unsigned int avail;
4819 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
4820 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
4821 int64_t signed_frames = out->written - kernel_buffer_size + avail;
4822 // This adjustment accounts for buffering after app processor.
4823 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07004824 signed_frames -=
Weiyin Jiang2da27362018-03-16 12:05:03 +08004825 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07004826
Weiyin Jiang2da27362018-03-16 12:05:03 +08004827 // Adjustment accounts for A2dp encoder latency with non offload usecases
4828 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
4829 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4830 signed_frames -=
4831 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4832 }
4833
4834 // It would be unusual for this value to be negative, but check just in case ...
4835 if (signed_frames >= 0) {
4836 *frames = signed_frames;
4837 ret = 0;
4838 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004839 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304840 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304841 *frames = out->written;
4842 clock_gettime(CLOCK_MONOTONIC, timestamp);
4843 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004844 }
4845 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004846 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004847 return ret;
4848}
4849
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004850static int out_set_callback(struct audio_stream_out *stream,
4851 stream_callback_t callback, void *cookie)
4852{
4853 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004854 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004855
4856 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004857 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004858 out->client_callback = callback;
4859 out->client_cookie = cookie;
4860 if (out->adsp_hdlr_stream_handle) {
4861 ret = audio_extn_adsp_hdlr_stream_set_callback(
4862 out->adsp_hdlr_stream_handle,
4863 callback,
4864 cookie);
4865 if (ret)
4866 ALOGW("%s:adsp hdlr callback registration failed %d",
4867 __func__, ret);
4868 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004869 pthread_mutex_unlock(&out->lock);
4870 return 0;
4871}
4872
4873static int out_pause(struct audio_stream_out* stream)
4874{
4875 struct stream_out *out = (struct stream_out *)stream;
4876 int status = -ENOSYS;
4877 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004878 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004879 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004880 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004881 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304882 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304883 status = compress_pause(out->compr);
4884
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004885 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004886
Mingming Yin21854652016-04-13 11:54:02 -07004887 if (audio_extn_passthru_is_active()) {
4888 ALOGV("offload use case, pause passthru");
4889 audio_extn_passthru_on_pause(out);
4890 }
4891
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304892 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004893 audio_extn_dts_notify_playback_state(out->usecase, 0,
4894 out->sample_rate, popcount(out->channel_mask),
4895 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004896 }
4897 pthread_mutex_unlock(&out->lock);
4898 }
4899 return status;
4900}
4901
4902static int out_resume(struct audio_stream_out* stream)
4903{
4904 struct stream_out *out = (struct stream_out *)stream;
4905 int status = -ENOSYS;
4906 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004907 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004908 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004909 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004910 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004911 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304912 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304913 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004914 }
4915 if (!status) {
4916 out->offload_state = OFFLOAD_STATE_PLAYING;
4917 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304918 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004919 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4920 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004921 }
4922 pthread_mutex_unlock(&out->lock);
4923 }
4924 return status;
4925}
4926
4927static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
4928{
4929 struct stream_out *out = (struct stream_out *)stream;
4930 int status = -ENOSYS;
4931 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004932 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004933 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004934 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
4935 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
4936 else
4937 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
4938 pthread_mutex_unlock(&out->lock);
4939 }
4940 return status;
4941}
4942
4943static int out_flush(struct audio_stream_out* stream)
4944{
4945 struct stream_out *out = (struct stream_out *)stream;
4946 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004947 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004948 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004949 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004950 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
4951 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004952 } else {
4953 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
4954 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08004955 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004956 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004957 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004958 return 0;
4959 }
4960 return -ENOSYS;
4961}
4962
Haynes Mathew George16081042017-05-31 17:16:49 -07004963static int out_stop(const struct audio_stream_out* stream)
4964{
4965 struct stream_out *out = (struct stream_out *)stream;
4966 struct audio_device *adev = out->dev;
4967 int ret = -ENOSYS;
4968
4969 ALOGV("%s", __func__);
4970 pthread_mutex_lock(&adev->lock);
4971 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4972 out->playback_started && out->pcm != NULL) {
4973 pcm_stop(out->pcm);
4974 ret = stop_output_stream(out);
4975 out->playback_started = false;
4976 }
4977 pthread_mutex_unlock(&adev->lock);
4978 return ret;
4979}
4980
4981static int out_start(const struct audio_stream_out* stream)
4982{
4983 struct stream_out *out = (struct stream_out *)stream;
4984 struct audio_device *adev = out->dev;
4985 int ret = -ENOSYS;
4986
4987 ALOGV("%s", __func__);
4988 pthread_mutex_lock(&adev->lock);
4989 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4990 !out->playback_started && out->pcm != NULL) {
4991 ret = start_output_stream(out);
4992 if (ret == 0) {
4993 out->playback_started = true;
4994 }
4995 }
4996 pthread_mutex_unlock(&adev->lock);
4997 return ret;
4998}
4999
5000/*
5001 * Modify config->period_count based on min_size_frames
5002 */
5003static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5004{
5005 int periodCountRequested = (min_size_frames + config->period_size - 1)
5006 / config->period_size;
5007 int periodCount = MMAP_PERIOD_COUNT_MIN;
5008
5009 ALOGV("%s original config.period_size = %d config.period_count = %d",
5010 __func__, config->period_size, config->period_count);
5011
5012 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5013 periodCount *= 2;
5014 }
5015 config->period_count = periodCount;
5016
5017 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5018}
5019
5020static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5021 int32_t min_size_frames,
5022 struct audio_mmap_buffer_info *info)
5023{
5024 struct stream_out *out = (struct stream_out *)stream;
5025 struct audio_device *adev = out->dev;
5026 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005027 unsigned int offset1 = 0;
5028 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005029 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005030 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005031
5032 ALOGV("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305033 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005034 pthread_mutex_lock(&adev->lock);
5035
Sharad Sanglec6f32552018-05-04 16:15:38 +05305036 if (CARD_STATUS_OFFLINE == out->card_status ||
5037 CARD_STATUS_OFFLINE == adev->card_status) {
5038 ALOGW("out->card_status or adev->card_status offline, try again");
5039 ret = -EIO;
5040 goto exit;
5041 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005042 if (info == NULL || min_size_frames == 0) {
5043 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5044 ret = -EINVAL;
5045 goto exit;
5046 }
5047 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5048 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5049 ret = -ENOSYS;
5050 goto exit;
5051 }
5052 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5053 if (out->pcm_device_id < 0) {
5054 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5055 __func__, out->pcm_device_id, out->usecase);
5056 ret = -EINVAL;
5057 goto exit;
5058 }
5059
5060 adjust_mmap_period_count(&out->config, min_size_frames);
5061
5062 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5063 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5064 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5065 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305066 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305067 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5068 out->card_status = CARD_STATUS_OFFLINE;
5069 adev->card_status = CARD_STATUS_OFFLINE;
5070 ret = -EIO;
5071 goto exit;
5072 }
5073
Haynes Mathew George16081042017-05-31 17:16:49 -07005074 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5075 step = "open";
5076 ret = -ENODEV;
5077 goto exit;
5078 }
5079 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5080 if (ret < 0) {
5081 step = "begin";
5082 goto exit;
5083 }
5084 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
5085 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005086 ret = platform_get_mmap_data_fd(adev->platform,
5087 out->pcm_device_id, 0 /*playback*/,
5088 &info->shared_memory_fd,
5089 &mmap_size);
5090 if (ret < 0) {
5091 step = "get_mmap_fd";
5092 goto exit;
5093 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005094 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005095 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005096
5097 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5098 if (ret < 0) {
5099 step = "commit";
5100 goto exit;
5101 }
5102
5103 out->standby = false;
5104 ret = 0;
5105
5106 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5107 __func__, info->shared_memory_address, info->buffer_size_frames);
5108
5109exit:
5110 if (ret != 0) {
5111 if (out->pcm == NULL) {
5112 ALOGE("%s: %s - %d", __func__, step, ret);
5113 } else {
5114 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5115 pcm_close(out->pcm);
5116 out->pcm = NULL;
5117 }
5118 }
5119 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305120 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005121 return ret;
5122}
5123
5124static int out_get_mmap_position(const struct audio_stream_out *stream,
5125 struct audio_mmap_position *position)
5126{
5127 struct stream_out *out = (struct stream_out *)stream;
5128 ALOGVV("%s", __func__);
5129 if (position == NULL) {
5130 return -EINVAL;
5131 }
5132 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005133 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005134 return -ENOSYS;
5135 }
5136 if (out->pcm == NULL) {
5137 return -ENOSYS;
5138 }
5139
5140 struct timespec ts = { 0, 0 };
5141 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5142 if (ret < 0) {
5143 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5144 return ret;
5145 }
5146 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
5147 return 0;
5148}
5149
5150
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005151/** audio_stream_in implementation **/
5152static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5153{
5154 struct stream_in *in = (struct stream_in *)stream;
5155
5156 return in->config.rate;
5157}
5158
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005159static int in_set_sample_rate(struct audio_stream *stream __unused,
5160 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005161{
5162 return -ENOSYS;
5163}
5164
5165static size_t in_get_buffer_size(const struct audio_stream *stream)
5166{
5167 struct stream_in *in = (struct stream_in *)stream;
5168
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005169 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5170 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005171 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5172 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 -07005173 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5174 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305175 else if(audio_extn_cin_attached_usecase(in->usecase))
5176 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005177
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005178 return in->config.period_size * in->af_period_multiplier *
5179 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005180}
5181
5182static uint32_t in_get_channels(const struct audio_stream *stream)
5183{
5184 struct stream_in *in = (struct stream_in *)stream;
5185
5186 return in->channel_mask;
5187}
5188
5189static audio_format_t in_get_format(const struct audio_stream *stream)
5190{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005191 struct stream_in *in = (struct stream_in *)stream;
5192
5193 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005194}
5195
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005196static int in_set_format(struct audio_stream *stream __unused,
5197 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005198{
5199 return -ENOSYS;
5200}
5201
5202static int in_standby(struct audio_stream *stream)
5203{
5204 struct stream_in *in = (struct stream_in *)stream;
5205 struct audio_device *adev = in->dev;
5206 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305207 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5208 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005209 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305210
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005211 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005212 if (!in->standby && in->is_st_session) {
5213 ALOGD("%s: sound trigger pcm stop lab", __func__);
5214 audio_extn_sound_trigger_stop_lab(in);
5215 in->standby = 1;
5216 }
5217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005218 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005219 if (adev->adm_deregister_stream)
5220 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5221
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005222 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005223 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005224 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005225 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005226 voice_extn_compress_voip_close_input_stream(stream);
5227 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005228 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5229 do_stop = in->capture_started;
5230 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005231 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305232 if (audio_extn_cin_attached_usecase(in->usecase))
5233 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005234 }
5235
5236 if (do_stop) {
Zhou Songa8895042016-07-05 17:54:22 +08005237 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005238 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005239 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005240 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005241 in->pcm = NULL;
5242 }
5243 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005244 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08005245 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005246 }
5247 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005248 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005249 return status;
5250}
5251
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005252static int in_dump(const struct audio_stream *stream __unused,
5253 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005254{
5255 return 0;
5256}
5257
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305258static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5259{
5260 if (!stream || !parms)
5261 return;
5262
5263 struct stream_in *in = (struct stream_in *)stream;
5264 struct audio_device *adev = in->dev;
5265
5266 card_status_t status;
5267 int card;
5268 if (parse_snd_card_status(parms, &card, &status) < 0)
5269 return;
5270
5271 pthread_mutex_lock(&adev->lock);
5272 bool valid_cb = (card == adev->snd_card);
5273 pthread_mutex_unlock(&adev->lock);
5274
5275 if (!valid_cb)
5276 return;
5277
5278 lock_input_stream(in);
5279 if (in->card_status != status)
5280 in->card_status = status;
5281 pthread_mutex_unlock(&in->lock);
5282
5283 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5284 use_case_table[in->usecase],
5285 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5286
5287 // a better solution would be to report error back to AF and let
5288 // it put the stream to standby
5289 if (status == CARD_STATUS_OFFLINE)
5290 in_standby(&in->stream.common);
5291
5292 return;
5293}
5294
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005295static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5296{
5297 struct stream_in *in = (struct stream_in *)stream;
5298 struct audio_device *adev = in->dev;
5299 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005300 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005301 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005302
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305303 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005304 parms = str_parms_create_str(kvpairs);
5305
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305306 if (!parms)
5307 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005308 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005309 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005310
5311 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5312 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005313 val = atoi(value);
5314 /* no audio source uses val == 0 */
5315 if ((in->source != val) && (val != 0)) {
5316 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005317 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5318 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5319 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005320 (in->config.rate == 8000 || in->config.rate == 16000 ||
5321 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005322 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005323 err = voice_extn_compress_voip_open_input_stream(in);
5324 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005325 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005326 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005327 }
5328 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005329 }
5330 }
5331
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005332 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5333 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005334 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005335 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5336
5337 // Workaround: If routing to an non existing usb device, fail gracefully
5338 // The routing request will otherwise block during 10 second
5339 int card;
5340 if (audio_is_usb_in_device(val) &&
5341 (card = get_alive_usb_card(parms)) >= 0) {
5342
5343 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5344 ret = -ENOSYS;
5345 } else {
5346
5347 in->device = val;
5348 /* If recording is in progress, change the tx device to new device */
5349 if (!in->standby && !in->is_st_session) {
5350 ALOGV("update input routing change");
5351 // inform adm before actual routing to prevent glitches.
5352 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005353 adev->adm_on_routing_change(adev->adm_data,
5354 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005355 ret = select_devices(adev, in->usecase);
5356 }
5357 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005358 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005359 }
5360 }
5361
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305362 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5363 if (err >= 0) {
5364 strlcpy(in->profile, value, sizeof(in->profile));
5365 ALOGV("updating stream profile with value '%s'", in->profile);
5366 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5367 &adev->streams_input_cfg_list,
5368 in->device, in->flags, in->format,
5369 in->sample_rate, in->bit_width,
5370 in->profile, &in->app_type_cfg);
5371 }
5372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005373 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005374 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005375
5376 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305377error:
Eric Laurent994a6932013-07-17 11:51:42 -07005378 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005379 return ret;
5380}
5381
5382static char* in_get_parameters(const struct audio_stream *stream,
5383 const char *keys)
5384{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005385 struct stream_in *in = (struct stream_in *)stream;
5386 struct str_parms *query = str_parms_create_str(keys);
5387 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005388 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005389
5390 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005391 if (reply) {
5392 str_parms_destroy(reply);
5393 }
5394 if (query) {
5395 str_parms_destroy(query);
5396 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005397 ALOGE("in_get_parameters: failed to create query or reply");
5398 return NULL;
5399 }
5400
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005401 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005402
5403 voice_extn_in_get_parameters(in, query, reply);
5404
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005405 stream_get_parameter_channels(query, reply,
5406 &in->supported_channel_masks[0]);
5407 stream_get_parameter_formats(query, reply,
5408 &in->supported_formats[0]);
5409 stream_get_parameter_rates(query, reply,
5410 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005411 str = str_parms_to_str(reply);
5412 str_parms_destroy(query);
5413 str_parms_destroy(reply);
5414
5415 ALOGV("%s: exit: returns - %s", __func__, str);
5416 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005417}
5418
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005419static int in_set_gain(struct audio_stream_in *stream __unused,
5420 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005421{
5422 return 0;
5423}
5424
5425static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5426 size_t bytes)
5427{
5428 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305429
5430 if (in == NULL) {
5431 ALOGE("%s: stream_in ptr is NULL", __func__);
5432 return -EINVAL;
5433 }
5434
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005435 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305436 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305437 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005438
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005439 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305440
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005441 if (in->is_st_session) {
5442 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5443 /* Read from sound trigger HAL */
5444 audio_extn_sound_trigger_read(in, buffer, bytes);
5445 pthread_mutex_unlock(&in->lock);
5446 return bytes;
5447 }
5448
Haynes Mathew George16081042017-05-31 17:16:49 -07005449 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5450 ret = -ENOSYS;
5451 goto exit;
5452 }
5453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005454 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005455 pthread_mutex_lock(&adev->lock);
5456 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5457 ret = voice_extn_compress_voip_start_input_stream(in);
5458 else
5459 ret = start_input_stream(in);
5460 pthread_mutex_unlock(&adev->lock);
5461 if (ret != 0) {
5462 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005463 }
5464 in->standby = 0;
5465 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005466
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005467 // what's the duration requested by the client?
5468 long ns = 0;
5469
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305470 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005471 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5472 in->config.rate;
5473
5474 request_in_focus(in, ns);
5475 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005476
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305477 if (audio_extn_cin_attached_usecase(in->usecase)) {
5478 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5479 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305480 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005481 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305482 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005483 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005484 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005485 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005486 } else if (audio_extn_ffv_get_stream() == in) {
5487 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305488 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005489 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305490 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5491 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5492 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5493 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305494 ret = -EINVAL;
5495 goto exit;
5496 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305497 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305498 ret = -errno;
5499 }
5500 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305501 /* bytes read is always set to bytes for non compress usecases */
5502 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005503 }
5504
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005505 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005507 /*
5508 * Instead of writing zeroes here, we could trust the hardware
5509 * to always provide zeroes when muted.
5510 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305511 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5512 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005513 memset(buffer, 0, bytes);
5514
5515exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005516 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305517 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005518 pthread_mutex_unlock(&in->lock);
5519
5520 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305521 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305522 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305523 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305524 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305525 in->standby = true;
5526 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305527 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5528 bytes_read = bytes;
5529 memset(buffer, 0, bytes);
5530 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005531 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005532 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305533 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305534 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005535 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305536 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005537}
5538
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005539static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005540{
5541 return 0;
5542}
5543
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005544static int add_remove_audio_effect(const struct audio_stream *stream,
5545 effect_handle_t effect,
5546 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005547{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005548 struct stream_in *in = (struct stream_in *)stream;
5549 int status = 0;
5550 effect_descriptor_t desc;
5551
5552 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005553 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5554
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005555 if (status != 0)
5556 return status;
5557
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005558 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005559 pthread_mutex_lock(&in->dev->lock);
kunleiz67646da2018-04-09 11:12:32 +08005560 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5561 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005562 in->enable_aec != enable &&
5563 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5564 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005565 if (!in->standby) {
5566 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5567 select_devices(in->dev, in->usecase);
5568 }
5569
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005570 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005571 if (in->enable_ns != enable &&
5572 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5573 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005574 if (!in->standby) {
kunleiz67646da2018-04-09 11:12:32 +08005575 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5576 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005577 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5578 select_devices(in->dev, in->usecase);
5579 } else
5580 select_devices(in->dev, in->usecase);
5581 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005582 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005583 pthread_mutex_unlock(&in->dev->lock);
5584 pthread_mutex_unlock(&in->lock);
5585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005586 return 0;
5587}
5588
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005589static int in_add_audio_effect(const struct audio_stream *stream,
5590 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005591{
Eric Laurent994a6932013-07-17 11:51:42 -07005592 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005593 return add_remove_audio_effect(stream, effect, true);
5594}
5595
5596static int in_remove_audio_effect(const struct audio_stream *stream,
5597 effect_handle_t effect)
5598{
Eric Laurent994a6932013-07-17 11:51:42 -07005599 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005600 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005601}
5602
Haynes Mathew George16081042017-05-31 17:16:49 -07005603static int in_stop(const struct audio_stream_in* stream)
5604{
5605 struct stream_in *in = (struct stream_in *)stream;
5606 struct audio_device *adev = in->dev;
5607
5608 int ret = -ENOSYS;
5609 ALOGV("%s", __func__);
5610 pthread_mutex_lock(&adev->lock);
5611 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5612 in->capture_started && in->pcm != NULL) {
5613 pcm_stop(in->pcm);
5614 ret = stop_input_stream(in);
5615 in->capture_started = false;
5616 }
5617 pthread_mutex_unlock(&adev->lock);
5618 return ret;
5619}
5620
5621static int in_start(const struct audio_stream_in* stream)
5622{
5623 struct stream_in *in = (struct stream_in *)stream;
5624 struct audio_device *adev = in->dev;
5625 int ret = -ENOSYS;
5626
5627 ALOGV("%s in %p", __func__, in);
5628 pthread_mutex_lock(&adev->lock);
5629 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5630 !in->capture_started && in->pcm != NULL) {
5631 if (!in->capture_started) {
5632 ret = start_input_stream(in);
5633 if (ret == 0) {
5634 in->capture_started = true;
5635 }
5636 }
5637 }
5638 pthread_mutex_unlock(&adev->lock);
5639 return ret;
5640}
5641
5642static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5643 int32_t min_size_frames,
5644 struct audio_mmap_buffer_info *info)
5645{
5646 struct stream_in *in = (struct stream_in *)stream;
5647 struct audio_device *adev = in->dev;
5648 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005649 unsigned int offset1 = 0;
5650 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005651 const char *step = "";
5652
5653 pthread_mutex_lock(&adev->lock);
5654 ALOGV("%s in %p", __func__, in);
5655
Sharad Sanglec6f32552018-05-04 16:15:38 +05305656 if (CARD_STATUS_OFFLINE == in->card_status||
5657 CARD_STATUS_OFFLINE == adev->card_status) {
5658 ALOGW("in->card_status or adev->card_status offline, try again");
5659 ret = -EIO;
5660 goto exit;
5661 }
5662
Haynes Mathew George16081042017-05-31 17:16:49 -07005663 if (info == NULL || min_size_frames == 0) {
5664 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5665 ret = -EINVAL;
5666 goto exit;
5667 }
5668 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5669 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5670 ALOGV("%s in %p", __func__, in);
5671 ret = -ENOSYS;
5672 goto exit;
5673 }
5674 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5675 if (in->pcm_device_id < 0) {
5676 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5677 __func__, in->pcm_device_id, in->usecase);
5678 ret = -EINVAL;
5679 goto exit;
5680 }
5681
5682 adjust_mmap_period_count(&in->config, min_size_frames);
5683
5684 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5685 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5686 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5687 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305688 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305689 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5690 in->card_status = CARD_STATUS_OFFLINE;
5691 adev->card_status = CARD_STATUS_OFFLINE;
5692 ret = -EIO;
5693 goto exit;
5694 }
5695
Haynes Mathew George16081042017-05-31 17:16:49 -07005696 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5697 step = "open";
5698 ret = -ENODEV;
5699 goto exit;
5700 }
5701
5702 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5703 if (ret < 0) {
5704 step = "begin";
5705 goto exit;
5706 }
5707 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5708 info->burst_size_frames = in->config.period_size;
5709 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
5710
5711 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
5712 info->buffer_size_frames));
5713
5714 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
5715 if (ret < 0) {
5716 step = "commit";
5717 goto exit;
5718 }
5719
5720 in->standby = false;
5721 ret = 0;
5722
5723 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5724 __func__, info->shared_memory_address, info->buffer_size_frames);
5725
5726exit:
5727 if (ret != 0) {
5728 if (in->pcm == NULL) {
5729 ALOGE("%s: %s - %d", __func__, step, ret);
5730 } else {
5731 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
5732 pcm_close(in->pcm);
5733 in->pcm = NULL;
5734 }
5735 }
5736 pthread_mutex_unlock(&adev->lock);
5737 return ret;
5738}
5739
5740static int in_get_mmap_position(const struct audio_stream_in *stream,
5741 struct audio_mmap_position *position)
5742{
5743 struct stream_in *in = (struct stream_in *)stream;
5744 ALOGVV("%s", __func__);
5745 if (position == NULL) {
5746 return -EINVAL;
5747 }
5748 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
5749 return -ENOSYS;
5750 }
5751 if (in->pcm == NULL) {
5752 return -ENOSYS;
5753 }
5754 struct timespec ts = { 0, 0 };
5755 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
5756 if (ret < 0) {
5757 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
5758 return ret;
5759 }
5760 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
5761 return 0;
5762}
5763
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305764int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07005765 audio_io_handle_t handle,
5766 audio_devices_t devices,
5767 audio_output_flags_t flags,
5768 struct audio_config *config,
5769 struct audio_stream_out **stream_out,
5770 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005771{
5772 struct audio_device *adev = (struct audio_device *)dev;
5773 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305774 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005775 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005776 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05305777 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005778 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
5779 bool is_usb_dev = audio_is_usb_out_device(devices) &&
5780 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
5781 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005782
kunleizb3fb48e2018-08-20 14:40:33 +08005783 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleiz7a6d9e02018-07-30 15:38:52 +08005784 is_usb_dev = false;
5785 devices = AUDIO_DEVICE_OUT_SPEAKER;
5786 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
5787 __func__, devices);
5788 }
5789
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005790 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005792 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
5793
Mingming Yin3a941d42016-02-17 18:08:05 -08005794 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
5795 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305796 devices, flags, &out->stream);
5797
5798
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005799 if (!out) {
5800 return -ENOMEM;
5801 }
5802
Haynes Mathew George204045b2015-02-25 20:32:03 -08005803 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005804 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305805 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08005806 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08005807 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005809 if (devices == AUDIO_DEVICE_NONE)
5810 devices = AUDIO_DEVICE_OUT_SPEAKER;
5811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005812 out->flags = flags;
5813 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07005814 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07005815 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005816 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05305817 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05305818 if (out->channel_mask == AUDIO_CHANNEL_NONE)
5819 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
5820 else
5821 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07005822 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005823 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08005824 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305825 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305826 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305827 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005828 out->hal_output_suspend_supported = 0;
5829 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05305830 out->set_dual_mono = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005831
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05305832 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05305833 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07005834 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
5835
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005836 if (audio_is_linear_pcm(out->format) &&
5837 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
5838 pthread_mutex_lock(&adev->lock);
5839 if (is_hdmi) {
5840 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
5841 ret = read_hdmi_sink_caps(out);
5842 } else if (is_usb_dev) {
5843 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
5844 &config->format,
5845 &out->supported_formats[0],
5846 MAX_SUPPORTED_FORMATS,
5847 &config->channel_mask,
5848 &out->supported_channel_masks[0],
5849 MAX_SUPPORTED_CHANNEL_MASKS,
5850 &config->sample_rate,
5851 &out->supported_sample_rates[0],
5852 MAX_SUPPORTED_SAMPLE_RATES);
5853 ALOGV("plugged dev USB ret %d", ret);
5854 } else {
5855 ret = -1;
5856 }
5857 pthread_mutex_unlock(&adev->lock);
5858 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005859 if (ret == -ENOSYS) {
5860 /* ignore and go with default */
5861 ret = 0;
5862 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005863 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08005864 goto error_open;
5865 }
5866 }
5867 }
5868
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005869 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07005870#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005871 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5872 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
5873 out->sample_rate == 32000 || out->sample_rate == 48000)) {
5874 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
5875 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
5876 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5877
5878 out->config = default_pcm_config_voip_copp;
5879 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5880 out->config.rate = out->sample_rate;
5881
5882#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05305883 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005884 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08005885 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005886 ret = voice_extn_compress_voip_open_output_stream(out);
5887 if (ret != 0) {
5888 ALOGE("%s: Compress voip output cannot be opened, error:%d",
5889 __func__, ret);
5890 goto error_open;
5891 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005892#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005893 } else if (audio_is_linear_pcm(out->format) &&
5894 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
5895 out->channel_mask = config->channel_mask;
5896 out->sample_rate = config->sample_rate;
5897 out->format = config->format;
5898 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
5899 // does this change?
5900 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
5901 out->config.rate = config->sample_rate;
5902 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
5903 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
5904 audio_bytes_per_sample(config->format));
5905 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07005906 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305907 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305908 pthread_mutex_lock(&adev->lock);
5909 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
5910 pthread_mutex_unlock(&adev->lock);
5911
5912 // reject offload during card offline to allow
5913 // fallback to s/w paths
5914 if (offline) {
5915 ret = -ENODEV;
5916 goto error_open;
5917 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005918
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005919 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
5920 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
5921 ALOGE("%s: Unsupported Offload information", __func__);
5922 ret = -EINVAL;
5923 goto error_open;
5924 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005925
Atul Khare3fa6e542017-08-09 00:56:17 +05305926 if (config->offload_info.format == 0)
5927 config->offload_info.format = config->format;
5928 if (config->offload_info.sample_rate == 0)
5929 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005930
Mingming Yin90310102013-11-13 16:57:00 -08005931 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305932 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07005933 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005934 ret = -EINVAL;
5935 goto error_open;
5936 }
5937
Ben Romberger0f8c87b2017-05-24 17:41:11 -07005938 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
5939 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
5940 (audio_extn_passthru_is_passthrough_stream(out)) &&
5941 !((config->sample_rate == 48000) ||
5942 (config->sample_rate == 96000) ||
5943 (config->sample_rate == 192000))) {
5944 ALOGE("%s: Unsupported sample rate %d for audio format %x",
5945 __func__, config->sample_rate, config->offload_info.format);
5946 ret = -EINVAL;
5947 goto error_open;
5948 }
5949
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005950 out->compr_config.codec = (struct snd_codec *)
5951 calloc(1, sizeof(struct snd_codec));
5952
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005953 if (!out->compr_config.codec) {
5954 ret = -ENOMEM;
5955 goto error_open;
5956 }
5957
Dhananjay Kumarac341582017-02-23 23:42:25 +05305958 out->stream.pause = out_pause;
5959 out->stream.resume = out_resume;
5960 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05305961 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305962 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07005963 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305964 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07005965 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05305966 } else {
5967 out->usecase = get_offload_usecase(adev, false /* is_compress */);
5968 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07005969 }
vivek mehta446c3962015-09-14 10:57:35 -07005970
5971 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005972 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5973 config->format == 0 && config->sample_rate == 0 &&
5974 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07005975 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08005976 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
5977 } else {
5978 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
5979 ret = -EEXIST;
5980 goto error_open;
5981 }
vivek mehta446c3962015-09-14 10:57:35 -07005982 }
5983
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005984 if (config->offload_info.channel_mask)
5985 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005986 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005987 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005988 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005989 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05305990 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005991 ret = -EINVAL;
5992 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005993 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005994
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005995 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005996 out->sample_rate = config->offload_info.sample_rate;
5997
Mingming Yin3ee55c62014-08-04 14:23:35 -07005998 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005999
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306000 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306001 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306002 audio_extn_dolby_send_ddp_endp_params(adev);
6003 audio_extn_dolby_set_dmid(adev);
6004 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006005
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006006 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006007 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006008 out->compr_config.codec->bit_rate =
6009 config->offload_info.bit_rate;
6010 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306011 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006012 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306013 /* Update bit width only for non passthrough usecases.
6014 * For passthrough usecases, the output will always be opened @16 bit
6015 */
6016 if (!audio_extn_passthru_is_passthrough_stream(out))
6017 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306018
6019 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6020 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6021 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6022
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006023 /*TODO: Do we need to change it for passthrough */
6024 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006025
Manish Dewangana6fc5442015-08-24 20:30:31 +05306026 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6027 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306028 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306029 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306030 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6031 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306032
6033 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6034 AUDIO_FORMAT_PCM) {
6035
6036 /*Based on platform support, configure appropriate alsa format for corresponding
6037 *hal input format.
6038 */
6039 out->compr_config.codec->format = hal_format_to_alsa(
6040 config->offload_info.format);
6041
Ashish Jain83a6cc22016-06-28 14:34:17 +05306042 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306043 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306044 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306045
Dhananjay Kumarac341582017-02-23 23:42:25 +05306046 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306047 *hal input format and alsa format might differ based on platform support.
6048 */
6049 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306050 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306051
6052 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6053
6054 /* Check if alsa session is configured with the same format as HAL input format,
6055 * if not then derive correct fragment size needed to accomodate the
6056 * conversion of HAL input format to alsa format.
6057 */
6058 audio_extn_utils_update_direct_pcm_fragment_size(out);
6059
6060 /*if hal input and output fragment size is different this indicates HAL input format is
6061 *not same as the alsa format
6062 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306063 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306064 /*Allocate a buffer to convert input data to the alsa configured format.
6065 *size of convert buffer is equal to the size required to hold one fragment size
6066 *worth of pcm data, this is because flinger does not write more than fragment_size
6067 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306068 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6069 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306070 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6071 ret = -ENOMEM;
6072 goto error_open;
6073 }
6074 }
6075 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6076 out->compr_config.fragment_size =
6077 audio_extn_passthru_get_buffer_size(&config->offload_info);
6078 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6079 } else {
6080 out->compr_config.fragment_size =
6081 platform_get_compress_offload_buffer_size(&config->offload_info);
6082 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6083 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006084
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306085 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6086 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6087 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006088 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306089 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006090
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306091 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6092 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6093 }
6094
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006095 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6096 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006097
Manish Dewangan69426c82017-01-30 17:35:36 +05306098 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6099 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6100 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6101 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6102 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6103 } else {
6104 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6105 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006106
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306107 memset(&out->channel_map_param, 0,
6108 sizeof(struct audio_out_channel_map_param));
6109
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006110 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306111 out->send_next_track_params = false;
6112 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006113 out->offload_state = OFFLOAD_STATE_IDLE;
6114 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006115 out->writeAt.tv_sec = 0;
6116 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006117
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006118 audio_extn_dts_create_state_notifier_node(out->usecase);
6119
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006120 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6121 __func__, config->offload_info.version,
6122 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306123
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306124 /* Check if DSD audio format is supported in codec
6125 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306126 */
6127
6128 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306129 (!platform_check_codec_dsd_support(adev->platform) ||
6130 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306131 ret = -EINVAL;
6132 goto error_open;
6133 }
6134
Ashish Jain5106d362016-05-11 19:23:33 +05306135 /* Disable gapless if any of the following is true
6136 * passthrough playback
6137 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306138 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306139 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306140 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306141 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006142 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306143 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306144 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306145 check_and_set_gapless_mode(adev, false);
6146 } else
6147 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006148
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306149 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006150 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6151 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306152 if (config->format == AUDIO_FORMAT_DSD) {
6153 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6154 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6155 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006156
6157 create_offload_callback_thread(out);
6158
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006159 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306160 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006161 if (ret != 0) {
6162 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
6163 __func__, ret);
6164 goto error_open;
6165 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006166 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
6167 if (config->sample_rate == 0)
6168 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6169 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6170 config->sample_rate != 8000) {
6171 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6172 ret = -EINVAL;
6173 goto error_open;
6174 }
6175 out->sample_rate = config->sample_rate;
6176 out->config.rate = config->sample_rate;
6177 if (config->format == AUDIO_FORMAT_DEFAULT)
6178 config->format = AUDIO_FORMAT_PCM_16_BIT;
6179 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6180 config->format = AUDIO_FORMAT_PCM_16_BIT;
6181 ret = -EINVAL;
6182 goto error_open;
6183 }
6184 out->format = config->format;
6185 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
6186 out->config = pcm_config_afe_proxy_playback;
6187 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006188 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05306189 unsigned int channels = 0;
6190 /*Update config params to default if not set by the caller*/
6191 if (config->sample_rate == 0)
6192 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6193 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6194 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6195 if (config->format == AUDIO_FORMAT_DEFAULT)
6196 config->format = AUDIO_FORMAT_PCM_16_BIT;
6197
6198 channels = audio_channel_count_from_out_mask(out->channel_mask);
6199
Varun Balaraje49253e2017-07-06 19:48:56 +05306200 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6201 out->usecase = get_interactive_usecase(adev);
6202 out->config = pcm_config_low_latency;
6203 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306204 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006205 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6206 out->flags);
6207 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006208 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6209 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6210 out->config = pcm_config_mmap_playback;
6211 out->stream.start = out_start;
6212 out->stream.stop = out_stop;
6213 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6214 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306215 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6216 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006217 out->hal_output_suspend_supported =
6218 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6219 out->dynamic_pm_qos_config_supported =
6220 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6221 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006222 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6223 } else {
6224 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6225 //the mixer path will be a string similar to "low-latency-playback resume"
6226 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6227 strlcat(out->pm_qos_mixer_path,
6228 " resume", MAX_MIXER_PATH_LEN);
6229 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6230 out->pm_qos_mixer_path);
6231 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306232 out->config = pcm_config_low_latency;
6233 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6234 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6235 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306236 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6237 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6238 if (out->config.period_size <= 0) {
6239 ALOGE("Invalid configuration period size is not valid");
6240 ret = -EINVAL;
6241 goto error_open;
6242 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306243 } else {
6244 /* primary path is the default path selected if no other outputs are available/suitable */
6245 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6246 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6247 }
6248 out->hal_ip_format = format = out->format;
6249 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6250 out->hal_op_format = pcm_format_to_hal(out->config.format);
6251 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6252 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006253 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306254 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306255 if (out->hal_ip_format != out->hal_op_format) {
6256 uint32_t buffer_size = out->config.period_size *
6257 format_to_bitwidth_table[out->hal_op_format] *
6258 out->config.channels;
6259 out->convert_buffer = calloc(1, buffer_size);
6260 if (out->convert_buffer == NULL){
6261 ALOGE("Allocation failed for convert buffer for size %d",
6262 out->compr_config.fragment_size);
6263 ret = -ENOMEM;
6264 goto error_open;
6265 }
6266 ALOGD("Convert buffer allocated of size %d", buffer_size);
6267 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006268 }
6269
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006270 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6271 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306272
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006273 /* TODO remove this hardcoding and check why width is zero*/
6274 if (out->bit_width == 0)
6275 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306276 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006277 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006278 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306279 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306280 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006281 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6282 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6283 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006284 if(adev->primary_output == NULL)
6285 adev->primary_output = out;
6286 else {
6287 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006288 ret = -EEXIST;
6289 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006290 }
6291 }
6292
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006293 /* Check if this usecase is already existing */
6294 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006295 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6296 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006297 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006298 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006299 ret = -EEXIST;
6300 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006301 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006302
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006303 pthread_mutex_unlock(&adev->lock);
6304
6305 out->stream.common.get_sample_rate = out_get_sample_rate;
6306 out->stream.common.set_sample_rate = out_set_sample_rate;
6307 out->stream.common.get_buffer_size = out_get_buffer_size;
6308 out->stream.common.get_channels = out_get_channels;
6309 out->stream.common.get_format = out_get_format;
6310 out->stream.common.set_format = out_set_format;
6311 out->stream.common.standby = out_standby;
6312 out->stream.common.dump = out_dump;
6313 out->stream.common.set_parameters = out_set_parameters;
6314 out->stream.common.get_parameters = out_get_parameters;
6315 out->stream.common.add_audio_effect = out_add_audio_effect;
6316 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6317 out->stream.get_latency = out_get_latency;
6318 out->stream.set_volume = out_set_volume;
6319 out->stream.write = out_write;
6320 out->stream.get_render_position = out_get_render_position;
6321 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006322 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006323
Haynes Mathew George16081042017-05-31 17:16:49 -07006324 if (out->realtime)
6325 out->af_period_multiplier = af_period_multiplier;
6326 else
6327 out->af_period_multiplier = 1;
6328
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006329 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006330 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006331 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006332
6333 config->format = out->stream.common.get_format(&out->stream.common);
6334 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6335 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
6336
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306337 /*
6338 By locking output stream before registering, we allow the callback
6339 to update stream's state only after stream's initial state is set to
6340 adev state.
6341 */
6342 lock_output_stream(out);
6343 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6344 pthread_mutex_lock(&adev->lock);
6345 out->card_status = adev->card_status;
6346 pthread_mutex_unlock(&adev->lock);
6347 pthread_mutex_unlock(&out->lock);
6348
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006349 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306350 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006351 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006352
6353 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6354 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6355 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006356 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306357 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006358 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006359 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306360 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006361 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6362 out->usecase, PCM_PLAYBACK);
6363 hdlr_stream_cfg.flags = out->flags;
6364 hdlr_stream_cfg.type = PCM_PLAYBACK;
6365 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6366 &hdlr_stream_cfg);
6367 if (ret) {
6368 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6369 out->adsp_hdlr_stream_handle = NULL;
6370 }
6371 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306372 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006373 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006374 if (ret < 0) {
6375 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6376 out->ip_hdlr_handle = NULL;
6377 }
6378 }
Eric Laurent994a6932013-07-17 11:51:42 -07006379 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006380 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006381
6382error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306383 if (out->convert_buffer)
6384 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006385 free(out);
6386 *stream_out = NULL;
6387 ALOGD("%s: exit: ret %d", __func__, ret);
6388 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006389}
6390
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306391void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006392 struct audio_stream_out *stream)
6393{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006394 struct stream_out *out = (struct stream_out *)stream;
6395 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006396 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006397
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006398 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306399
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306400 // must deregister from sndmonitor first to prevent races
6401 // between the callback and close_stream
6402 audio_extn_snd_mon_unregister_listener(out);
6403
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006404 /* close adsp hdrl session before standby */
6405 if (out->adsp_hdlr_stream_handle) {
6406 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6407 if (ret)
6408 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6409 out->adsp_hdlr_stream_handle = NULL;
6410 }
6411
Manish Dewangan21a850a2017-08-14 12:03:55 +05306412 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006413 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6414 out->ip_hdlr_handle = NULL;
6415 }
6416
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006417 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306418 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006419 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306420 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306421 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006422 if(ret != 0)
6423 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6424 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006425 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006426 out_standby(&stream->common);
6427
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006428 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006429 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006430 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006431 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006432 if (out->compr_config.codec != NULL)
6433 free(out->compr_config.codec);
6434 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006435
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306436 out->a2dp_compress_mute = false;
6437
Varun Balaraje49253e2017-07-06 19:48:56 +05306438 if (is_interactive_usecase(out->usecase))
6439 free_interactive_usecase(adev, out->usecase);
6440
Ashish Jain83a6cc22016-06-28 14:34:17 +05306441 if (out->convert_buffer != NULL) {
6442 free(out->convert_buffer);
6443 out->convert_buffer = NULL;
6444 }
6445
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006446 if (adev->voice_tx_output == out)
6447 adev->voice_tx_output = NULL;
6448
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306449 if (adev->primary_output == out)
6450 adev->primary_output = NULL;
6451
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006452 pthread_cond_destroy(&out->cond);
6453 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006454 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006455 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006456}
6457
6458static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6459{
6460 struct audio_device *adev = (struct audio_device *)dev;
6461 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006462 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006463 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006464 int ret;
6465 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006466
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006467 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006468 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006469
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306470 if (!parms)
6471 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306472
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306473 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6474 if (ret >= 0) {
6475 /* When set to false, HAL should disable EC and NS */
6476 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6477 adev->bt_sco_on = true;
6478 else
6479 adev->bt_sco_on = false;
6480 }
6481
Naresh Tanniru4c630392014-05-12 01:05:52 +05306482 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006483 status = voice_set_parameters(adev, parms);
6484 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006485 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006486
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006487 status = platform_set_parameters(adev->platform, parms);
6488 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006489 goto done;
6490
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006491 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6492 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006493 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006494 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6495 adev->bluetooth_nrec = true;
6496 else
6497 adev->bluetooth_nrec = false;
6498 }
6499
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006500 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6501 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006502 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6503 adev->screen_off = false;
6504 else
6505 adev->screen_off = true;
6506 }
6507
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006508 ret = str_parms_get_int(parms, "rotation", &val);
6509 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006510 bool reverse_speakers = false;
6511 switch(val) {
6512 // FIXME: note that the code below assumes that the speakers are in the correct placement
6513 // relative to the user when the device is rotated 90deg from its default rotation. This
6514 // assumption is device-specific, not platform-specific like this code.
6515 case 270:
6516 reverse_speakers = true;
6517 break;
6518 case 0:
6519 case 90:
6520 case 180:
6521 break;
6522 default:
6523 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006524 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006525 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006526 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006527 // check and set swap
6528 // - check if orientation changed and speaker active
6529 // - set rotation and cache the rotation value
6530 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006531 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006532 }
6533
Mingming Yin514a8bc2014-07-29 15:22:21 -07006534 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6535 if (ret >= 0) {
6536 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6537 adev->bt_wb_speech_enabled = true;
6538 else
6539 adev->bt_wb_speech_enabled = false;
6540 }
6541
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006542 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6543 if (ret >= 0) {
6544 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306545 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08006546 if (audio_is_output_device(val) &&
6547 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006548 ALOGV("cache new ext disp type and edid");
6549 ret = platform_get_ext_disp_type(adev->platform);
6550 if (ret < 0) {
6551 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08006552 status = ret;
6553 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006554 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006555 platform_cache_edid(adev->platform);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306556 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07006557 /*
6558 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6559 * Per AudioPolicyManager, USB device is higher priority than WFD.
6560 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6561 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6562 * starting voice call on USB
6563 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006564 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306565 if (ret >= 0)
6566 audio_extn_usb_add_device(device, atoi(value));
6567
Zhou Song6f862822017-11-06 17:27:57 +08006568 if (!audio_extn_usb_is_tunnel_supported()) {
6569 ALOGV("detected USB connect .. disable proxy");
6570 adev->allow_afe_proxy_usage = false;
6571 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006572 }
6573 }
6574
6575 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6576 if (ret >= 0) {
6577 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306578 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07006579 /*
6580 * The HDMI / Displayport disconnect handling has been moved to
6581 * audio extension to ensure that its parameters are not
6582 * invalidated prior to updating sysfs of the disconnect event
6583 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6584 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306585 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006586 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306587 if (ret >= 0)
6588 audio_extn_usb_remove_device(device, atoi(value));
6589
Zhou Song6f862822017-11-06 17:27:57 +08006590 if (!audio_extn_usb_is_tunnel_supported()) {
6591 ALOGV("detected USB disconnect .. enable proxy");
6592 adev->allow_afe_proxy_usage = true;
6593 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006594 }
6595 }
6596
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306597 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6598 if (ret >= 0) {
6599 struct audio_usecase *usecase;
6600 struct listnode *node;
6601 list_for_each(node, &adev->usecase_list) {
6602 usecase = node_to_item(node, struct audio_usecase, list);
6603 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07006604 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306605 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08006606
6607 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306608 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08006609 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306610 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306611 //force device switch to re configure encoder
6612 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306613 audio_extn_a2dp_set_handoff_mode(false);
6614 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306615 break;
6616 }
6617 }
6618 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006619
6620 //handle vr audio setparam
6621 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6622 value, sizeof(value));
6623 if (ret >= 0) {
6624 ALOGI("Setting vr mode to be %s", value);
6625 if (!strncmp(value, "true", 4)) {
6626 adev->vr_audio_mode_enabled = true;
6627 ALOGI("Setting vr mode to true");
6628 } else if (!strncmp(value, "false", 5)) {
6629 adev->vr_audio_mode_enabled = false;
6630 ALOGI("Setting vr mode to false");
6631 } else {
6632 ALOGI("wrong vr mode set");
6633 }
6634 }
6635
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306636 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006637done:
6638 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006639 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306640error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006641 ALOGV("%s: exit with code(%d)", __func__, status);
6642 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006643}
6644
6645static char* adev_get_parameters(const struct audio_hw_device *dev,
6646 const char *keys)
6647{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006648 struct audio_device *adev = (struct audio_device *)dev;
6649 struct str_parms *reply = str_parms_create();
6650 struct str_parms *query = str_parms_create_str(keys);
6651 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05306652 char value[256] = {0};
6653 int ret = 0;
6654
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006655 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006656 if (reply) {
6657 str_parms_destroy(reply);
6658 }
6659 if (query) {
6660 str_parms_destroy(query);
6661 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006662 ALOGE("adev_get_parameters: failed to create query or reply");
6663 return NULL;
6664 }
6665
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006666 //handle vr audio getparam
6667
6668 ret = str_parms_get_str(query,
6669 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6670 value, sizeof(value));
6671
6672 if (ret >= 0) {
6673 bool vr_audio_enabled = false;
6674 pthread_mutex_lock(&adev->lock);
6675 vr_audio_enabled = adev->vr_audio_mode_enabled;
6676 pthread_mutex_unlock(&adev->lock);
6677
6678 ALOGI("getting vr mode to %d", vr_audio_enabled);
6679
6680 if (vr_audio_enabled) {
6681 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6682 "true");
6683 goto exit;
6684 } else {
6685 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6686 "false");
6687 goto exit;
6688 }
6689 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006690
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006691 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006692 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08006693 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006694 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05306695 pthread_mutex_unlock(&adev->lock);
6696
Naresh Tannirud7205b62014-06-20 02:54:48 +05306697exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006698 str = str_parms_to_str(reply);
6699 str_parms_destroy(query);
6700 str_parms_destroy(reply);
6701
6702 ALOGV("%s: exit: returns - %s", __func__, str);
6703 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006704}
6705
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006706static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006707{
6708 return 0;
6709}
6710
6711static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
6712{
Haynes Mathew George5191a852013-09-11 14:19:36 -07006713 int ret;
6714 struct audio_device *adev = (struct audio_device *)dev;
6715 pthread_mutex_lock(&adev->lock);
6716 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07006717 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07006718 pthread_mutex_unlock(&adev->lock);
6719 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006720}
6721
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006722static int adev_set_master_volume(struct audio_hw_device *dev __unused,
6723 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006724{
6725 return -ENOSYS;
6726}
6727
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006728static int adev_get_master_volume(struct audio_hw_device *dev __unused,
6729 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006730{
6731 return -ENOSYS;
6732}
6733
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006734static int adev_set_master_mute(struct audio_hw_device *dev __unused,
6735 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006736{
6737 return -ENOSYS;
6738}
6739
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006740static int adev_get_master_mute(struct audio_hw_device *dev __unused,
6741 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006742{
6743 return -ENOSYS;
6744}
6745
6746static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
6747{
6748 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006750 pthread_mutex_lock(&adev->lock);
6751 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006752 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006753 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08006754 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006755 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07006756 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006757 adev->current_call_output = NULL;
6758 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006759 }
6760 pthread_mutex_unlock(&adev->lock);
6761 return 0;
6762}
6763
6764static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
6765{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006766 int ret;
6767
6768 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08006769 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006770 ret = voice_set_mic_mute((struct audio_device *)dev, state);
6771 pthread_mutex_unlock(&adev->lock);
6772
6773 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006774}
6775
6776static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
6777{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006778 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006779 return 0;
6780}
6781
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006782static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006783 const struct audio_config *config)
6784{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006785 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006786
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006787 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
6788 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006789}
6790
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006791static bool adev_input_allow_hifi_record(struct audio_device *adev,
6792 audio_devices_t devices,
6793 audio_input_flags_t flags,
6794 audio_source_t source) {
6795 const bool allowed = true;
6796
6797 if (!audio_is_usb_in_device(devices))
6798 return !allowed;
6799
6800 switch (flags) {
6801 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006802 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07006803 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
6804 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006805 default:
6806 return !allowed;
6807 }
6808
6809 switch (source) {
6810 case AUDIO_SOURCE_DEFAULT:
6811 case AUDIO_SOURCE_MIC:
6812 case AUDIO_SOURCE_UNPROCESSED:
6813 break;
6814 default:
6815 return !allowed;
6816 }
6817
6818 switch (adev->mode) {
6819 case 0:
6820 break;
6821 default:
6822 return !allowed;
6823 }
6824
6825 return allowed;
6826}
6827
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006828static int adev_update_voice_comm_input_stream(struct stream_in *in,
6829 struct audio_config *config)
6830{
6831 bool valid_rate = (config->sample_rate == 8000 ||
6832 config->sample_rate == 16000 ||
6833 config->sample_rate == 32000 ||
6834 config->sample_rate == 48000);
6835 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
6836
6837#ifndef COMPRESS_VOIP_ENABLED
kunleiz67646da2018-04-09 11:12:32 +08006838 if (valid_rate && valid_ch &&
6839 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006840 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6841 in->config = default_pcm_config_voip_copp;
6842 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
6843 DEFAULT_VOIP_BUF_DURATION_MS,
6844 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6845 } else {
kunleiz99754d02018-04-24 10:53:17 +08006846 ALOGW("%s No valid input in voip, use defaults"
6847 "sample rate %u, channel mask 0x%X",
6848 __func__, config->sample_rate, in->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006849 }
6850 in->config.rate = config->sample_rate;
6851 in->sample_rate = config->sample_rate;
6852#else
6853 //XXX needed for voice_extn_compress_voip_open_input_stream
6854 in->config.rate = config->sample_rate;
6855 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6856 voice_extn_compress_voip_is_active(in->dev)) &&
6857 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6858 valid_rate && valid_ch) {
6859 voice_extn_compress_voip_open_input_stream(in);
6860 // update rate entries to match config from AF
6861 in->config.rate = config->sample_rate;
6862 in->sample_rate = config->sample_rate;
6863 } else {
6864 ALOGW("%s compress voip not active, use defaults", __func__);
6865 }
6866#endif
6867 return 0;
6868}
6869
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006870static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006871 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006872 audio_devices_t devices,
6873 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006874 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306875 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006876 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006877 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006878{
6879 struct audio_device *adev = (struct audio_device *)dev;
6880 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006881 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006882 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006883 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306884 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006885 bool is_usb_dev = audio_is_usb_in_device(devices);
6886 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
6887 devices,
6888 flags,
6889 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306890
kunleizb3fb48e2018-08-20 14:40:33 +08006891 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleiz7a6d9e02018-07-30 15:38:52 +08006892 is_usb_dev = false;
6893 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
6894 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
6895 __func__, devices);
6896 }
6897
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006898 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006899
6900 if (!(is_usb_dev && may_use_hifi_record)) {
6901 if (config->sample_rate == 0)
6902 config->sample_rate = 48000;
6903 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6904 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
6905 if (config->format == AUDIO_FORMAT_DEFAULT)
6906 config->format = AUDIO_FORMAT_PCM_16_BIT;
6907
6908 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
6909
6910 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
6911 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05306912 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006913
6914 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006915
6916 if (!in) {
6917 ALOGE("failed to allocate input stream");
6918 return -ENOMEM;
6919 }
6920
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306921 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306922 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
6923 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006924 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006925 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006926
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006927 in->stream.common.get_sample_rate = in_get_sample_rate;
6928 in->stream.common.set_sample_rate = in_set_sample_rate;
6929 in->stream.common.get_buffer_size = in_get_buffer_size;
6930 in->stream.common.get_channels = in_get_channels;
6931 in->stream.common.get_format = in_get_format;
6932 in->stream.common.set_format = in_set_format;
6933 in->stream.common.standby = in_standby;
6934 in->stream.common.dump = in_dump;
6935 in->stream.common.set_parameters = in_set_parameters;
6936 in->stream.common.get_parameters = in_get_parameters;
6937 in->stream.common.add_audio_effect = in_add_audio_effect;
6938 in->stream.common.remove_audio_effect = in_remove_audio_effect;
6939 in->stream.set_gain = in_set_gain;
6940 in->stream.read = in_read;
6941 in->stream.get_input_frames_lost = in_get_input_frames_lost;
6942
6943 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006944 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006945 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006946 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006947 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006948 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07006949 in->bit_width = 16;
6950 in->af_period_multiplier = 1;
6951
6952 /* Update config params with the requested sample rate and channels */
6953 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
6954 (adev->mode != AUDIO_MODE_IN_CALL)) {
6955 ret = -EINVAL;
6956 goto err_open;
6957 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006958
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006959 if (is_usb_dev && may_use_hifi_record) {
6960 /* HiFi record selects an appropriate format, channel, rate combo
6961 depending on sink capabilities*/
6962 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
6963 &config->format,
6964 &in->supported_formats[0],
6965 MAX_SUPPORTED_FORMATS,
6966 &config->channel_mask,
6967 &in->supported_channel_masks[0],
6968 MAX_SUPPORTED_CHANNEL_MASKS,
6969 &config->sample_rate,
6970 &in->supported_sample_rates[0],
6971 MAX_SUPPORTED_SAMPLE_RATES);
6972 if (ret != 0) {
6973 ret = -EINVAL;
6974 goto err_open;
6975 }
6976 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006977 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306978 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05306979 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
6980 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
6981 in->config.format = PCM_FORMAT_S32_LE;
6982 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306983 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
6984 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
6985 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
6986 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6987 bool ret_error = false;
6988 in->bit_width = 24;
6989 /* 24 bit is restricted to UNPROCESSED source only,also format supported
6990 from HAL is 24_packed and 8_24
6991 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
6992 24_packed return error indicating supported format is 24_packed
6993 *> In case of any other source requesting 24 bit or float return error
6994 indicating format supported is 16 bit only.
6995
6996 on error flinger will retry with supported format passed
6997 */
6998 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
6999 (source != AUDIO_SOURCE_CAMCORDER)) {
7000 config->format = AUDIO_FORMAT_PCM_16_BIT;
7001 if (config->sample_rate > 48000)
7002 config->sample_rate = 48000;
7003 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07007004 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
7005 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307006 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
7007 ret_error = true;
7008 }
7009
7010 if (ret_error) {
7011 ret = -EINVAL;
7012 goto err_open;
7013 }
7014 }
7015
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007016 in->channel_mask = config->channel_mask;
7017 in->format = config->format;
7018
7019 in->usecase = USECASE_AUDIO_RECORD;
7020 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
7021 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
7022 is_low_latency = true;
7023#if LOW_LATENCY_CAPTURE_USE_CASE
7024 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
7025#endif
7026 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
7027 }
7028
7029 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
7030 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
7031 in->realtime = 0;
7032 in->usecase = USECASE_AUDIO_RECORD_MMAP;
7033 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07007034 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007035 in->stream.start = in_start;
7036 in->stream.stop = in_stop;
7037 in->stream.create_mmap_buffer = in_create_mmap_buffer;
7038 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georged2d7bc32018-01-31 12:48:20 -08007039 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007040 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
7041 } else if (in->realtime) {
7042 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07007043 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007044 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007045 in->sample_rate = in->config.rate;
7046 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07007047 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007048 in->usecase = USECASE_AUDIO_RECORD_HIFI;
7049 in->config = pcm_config_audio_capture;
7050 frame_size = audio_stream_in_frame_size(&in->stream);
7051 buffer_size = get_input_buffer_size(config->sample_rate,
7052 config->format,
7053 channel_count,
7054 false /*is_low_latency*/);
7055 in->config.period_size = buffer_size / frame_size;
7056 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007057 in->config.format = pcm_format_from_audio_format(config->format);
7058 in->config.channels = channel_count;
Haynes Mathew Georged2d7bc32018-01-31 12:48:20 -08007059 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007060 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05307061 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007062 if (config->sample_rate == 0)
7063 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7064 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
7065 config->sample_rate != 8000) {
7066 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7067 ret = -EINVAL;
7068 goto err_open;
7069 }
7070 if (config->format == AUDIO_FORMAT_DEFAULT)
7071 config->format = AUDIO_FORMAT_PCM_16_BIT;
7072 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
7073 config->format = AUDIO_FORMAT_PCM_16_BIT;
7074 ret = -EINVAL;
7075 goto err_open;
7076 }
7077
7078 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
7079 in->config = pcm_config_afe_proxy_record;
7080 in->config.channels = channel_count;
7081 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307082 in->sample_rate = config->sample_rate;
Haynes Mathew George46740472017-10-27 18:40:12 -07007083 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05307084 int ret_val;
7085 pthread_mutex_lock(&adev->lock);
7086 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
7087 in, config, &channel_mask_updated);
7088 pthread_mutex_unlock(&adev->lock);
7089
7090 if (!ret_val) {
7091 if (channel_mask_updated == true) {
7092 ALOGD("%s: return error to retry with updated channel mask (%#x)",
7093 __func__, config->channel_mask);
7094 ret = -EINVAL;
7095 goto err_open;
7096 }
7097 ALOGD("%s: created multi-channel session succesfully",__func__);
7098 } else if (audio_extn_compr_cap_enabled() &&
7099 audio_extn_compr_cap_format_supported(config->format) &&
7100 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
7101 audio_extn_compr_cap_init(in);
7102 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05307103 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05307104 ret = audio_extn_cin_configure_input_stream(in);
7105 if (ret)
7106 goto err_open;
7107 } else {
7108 in->config = pcm_config_audio_capture;
7109 in->config.rate = config->sample_rate;
7110 in->config.format = pcm_format_from_audio_format(config->format);
7111 in->config.channels = channel_count;
7112 in->sample_rate = config->sample_rate;
7113 in->format = config->format;
7114 frame_size = audio_stream_in_frame_size(&in->stream);
7115 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07007116 config->format,
7117 channel_count,
7118 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02007119 /* prevent division-by-zero */
7120 if (frame_size == 0) {
7121 ALOGE("%s: Error frame_size==0", __func__);
7122 ret = -EINVAL;
7123 goto err_open;
7124 }
7125
Revathi Uddarajud2634032017-12-07 14:42:34 +05307126 in->config.period_size = buffer_size / frame_size;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007127
Revathi Uddarajud2634032017-12-07 14:42:34 +05307128 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
7129 /* optionally use VOIP usecase depending on config(s) */
7130 ret = adev_update_voice_comm_input_stream(in, config);
7131 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007132
Revathi Uddarajud2634032017-12-07 14:42:34 +05307133 if (ret) {
7134 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
7135 goto err_open;
7136 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007137 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007138 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307139 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7140 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007141 devices, flags, in->format,
7142 in->sample_rate, in->bit_width,
7143 in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307144
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007145 /* This stream could be for sound trigger lab,
7146 get sound trigger pcm if present */
7147 audio_extn_sound_trigger_check_and_get_session(in);
7148
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307149 lock_input_stream(in);
7150 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
7151 pthread_mutex_lock(&adev->lock);
7152 in->card_status = adev->card_status;
7153 pthread_mutex_unlock(&adev->lock);
7154 pthread_mutex_unlock(&in->lock);
7155
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007156 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07007157 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007158 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007159
7160err_open:
7161 free(in);
7162 *stream_in = NULL;
7163 return ret;
7164}
7165
7166static void adev_close_input_stream(struct audio_hw_device *dev,
7167 struct audio_stream_in *stream)
7168{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007169 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007170 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007171 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307172
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307173 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007174
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307175 // must deregister from sndmonitor first to prevent races
7176 // between the callback and close_stream
7177 audio_extn_snd_mon_unregister_listener(stream);
7178
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307179 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07007180 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307181
Pallavid7c7a272018-01-16 11:22:55 +05307182 if (in == NULL) {
7183 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
7184 return;
7185 }
7186
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007187 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307188 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007189 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307190 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007191 if (ret != 0)
7192 ALOGE("%s: Compress voip input cannot be closed, error:%d",
7193 __func__, ret);
7194 } else
7195 in_standby(&stream->common);
7196
Revathi Uddarajud2634032017-12-07 14:42:34 +05307197 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07007198 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007199 audio_extn_ssr_deinit();
7200 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007201
Garmond Leunge2433c32017-09-28 21:51:22 -07007202 if (audio_extn_ffv_get_stream() == in) {
7203 audio_extn_ffv_stream_deinit();
7204 }
7205
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307206 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07007207 audio_extn_compr_cap_format_supported(in->config.format))
7208 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05307209
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307210 if (audio_extn_cin_attached_usecase(in->usecase))
7211 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007212
Mingming Yinfd7607b2016-01-22 12:48:44 -08007213 if (in->is_st_session) {
7214 ALOGV("%s: sound trigger pcm stop lab", __func__);
7215 audio_extn_sound_trigger_stop_lab(in);
7216 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007217 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307218 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007219 return;
7220}
7221
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307222int adev_create_audio_patch(struct audio_hw_device *dev,
7223 unsigned int num_sources,
7224 const struct audio_port_config *sources,
7225 unsigned int num_sinks,
7226 const struct audio_port_config *sinks,
7227 audio_patch_handle_t *handle)
7228{
7229
7230
7231 return audio_extn_hw_loopback_create_audio_patch(dev,
7232 num_sources,
7233 sources,
7234 num_sinks,
7235 sinks,
7236 handle);
7237
7238}
7239
7240int adev_release_audio_patch(struct audio_hw_device *dev,
7241 audio_patch_handle_t handle)
7242{
7243 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
7244}
7245
7246int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
7247{
7248 return audio_extn_hw_loopback_get_audio_port(dev, config);
7249}
7250
7251int adev_set_audio_port_config(struct audio_hw_device *dev,
7252 const struct audio_port_config *config)
7253{
7254 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
7255}
7256
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007257static int adev_dump(const audio_hw_device_t *device __unused,
7258 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007259{
7260 return 0;
7261}
7262
7263static int adev_close(hw_device_t *device)
7264{
7265 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07007266
7267 if (!adev)
7268 return 0;
7269
7270 pthread_mutex_lock(&adev_init_lock);
7271
7272 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307273 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007274 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08007275 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307276 audio_extn_utils_release_streams_cfg_lists(
7277 &adev->streams_output_cfg_list,
7278 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307279 if (audio_extn_qaf_is_enabled())
7280 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007281 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007282 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007283 free(adev->snd_dev_ref_cnt);
7284 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007285 if (adev->adm_deinit)
7286 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307287 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007288 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307289 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307290 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007291 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307292 if (adev->device_cfg_params) {
7293 free(adev->device_cfg_params);
7294 adev->device_cfg_params = NULL;
7295 }
Kiran Kandi910e1862013-10-29 13:29:42 -07007296 free(device);
7297 adev = NULL;
7298 }
7299 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007301 return 0;
7302}
7303
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007304/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
7305 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
7306 * just that it _might_ work.
7307 */
7308static int period_size_is_plausible_for_low_latency(int period_size)
7309{
7310 switch (period_size) {
7311 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07007312 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007313 case 240:
7314 case 320:
7315 case 480:
7316 return 1;
7317 default:
7318 return 0;
7319 }
7320}
7321
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307322static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
7323{
7324 bool is_snd_card_status = false;
7325 bool is_ext_device_status = false;
7326 char value[32];
7327 int card = -1;
7328 card_status_t status;
7329
7330 if (cookie != adev || !parms)
7331 return;
7332
7333 if (!parse_snd_card_status(parms, &card, &status)) {
7334 is_snd_card_status = true;
7335 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
7336 is_ext_device_status = true;
7337 } else {
7338 // not a valid event
7339 return;
7340 }
7341
7342 pthread_mutex_lock(&adev->lock);
7343 if (card == adev->snd_card || is_ext_device_status) {
7344 if (is_snd_card_status && adev->card_status != status) {
7345 adev->card_status = status;
7346 platform_snd_card_update(adev->platform, status);
7347 audio_extn_fm_set_parameters(adev, parms);
7348 } else if (is_ext_device_status) {
7349 platform_set_parameters(adev->platform, parms);
7350 }
7351 }
7352 pthread_mutex_unlock(&adev->lock);
7353 return;
7354}
7355
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307356/* out and adev lock held */
7357static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
7358{
7359 struct audio_usecase *uc_info;
7360 float left_p;
7361 float right_p;
7362 audio_devices_t devices;
7363
7364 uc_info = get_usecase_from_list(adev, out->usecase);
7365 if (uc_info == NULL) {
7366 ALOGE("%s: Could not find the usecase (%d) in the list",
7367 __func__, out->usecase);
7368 return -EINVAL;
7369 }
7370
7371 ALOGD("%s: enter: usecase(%d: %s)", __func__,
7372 out->usecase, use_case_table[out->usecase]);
7373
7374 if (restore) {
7375 // restore A2DP device for active usecases and unmute if required
7376 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
7377 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
7378 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
7379 select_devices(adev, uc_info->id);
7380 pthread_mutex_lock(&out->compr_mute_lock);
7381 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7382 (out->a2dp_compress_mute)) {
7383 out->a2dp_compress_mute = false;
7384 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
7385 }
7386 pthread_mutex_unlock(&out->compr_mute_lock);
7387 }
7388 } else {
7389 // mute compress stream if suspended
7390 pthread_mutex_lock(&out->compr_mute_lock);
7391 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7392 (!out->a2dp_compress_mute)) {
7393 if (!out->standby) {
7394 ALOGD("%s: selecting speaker and muting stream", __func__);
7395 devices = out->devices;
7396 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
7397 left_p = out->volume_l;
7398 right_p = out->volume_r;
7399 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7400 compress_pause(out->compr);
7401 out_set_compr_volume(&out->stream, (float)0, (float)0);
7402 out->a2dp_compress_mute = true;
7403 select_devices(adev, out->usecase);
7404 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7405 compress_resume(out->compr);
7406 out->devices = devices;
7407 out->volume_l = left_p;
7408 out->volume_r = right_p;
7409 }
7410 }
7411 pthread_mutex_unlock(&out->compr_mute_lock);
7412 }
7413 ALOGV("%s: exit", __func__);
7414 return 0;
7415}
7416
7417int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
7418{
7419 int ret = 0;
7420
7421 lock_output_stream(out);
7422 pthread_mutex_lock(&adev->lock);
7423
7424 ret = check_a2dp_restore_l(adev, out, restore);
7425
7426 pthread_mutex_unlock(&adev->lock);
7427 pthread_mutex_unlock(&out->lock);
7428 return ret;
7429}
7430
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007431static int adev_open(const hw_module_t *module, const char *name,
7432 hw_device_t **device)
7433{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307434 int ret;
7435
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007436 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007437 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
7438
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007439 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07007440 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007441 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07007442 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007443 ALOGD("%s: returning existing instance of adev", __func__);
7444 ALOGD("%s: exit", __func__);
7445 pthread_mutex_unlock(&adev_init_lock);
7446 return 0;
7447 }
7448
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007449 adev = calloc(1, sizeof(struct audio_device));
7450
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007451 if (!adev) {
7452 pthread_mutex_unlock(&adev_init_lock);
7453 return -ENOMEM;
7454 }
7455
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007456 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
7457
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05307458#ifdef DYNAMIC_LOG_ENABLED
7459 register_for_dynamic_logging("hal");
7460#endif
7461
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007462 adev->device.common.tag = HARDWARE_DEVICE_TAG;
7463 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7464 adev->device.common.module = (struct hw_module_t *)module;
7465 adev->device.common.close = adev_close;
7466
7467 adev->device.init_check = adev_init_check;
7468 adev->device.set_voice_volume = adev_set_voice_volume;
7469 adev->device.set_master_volume = adev_set_master_volume;
7470 adev->device.get_master_volume = adev_get_master_volume;
7471 adev->device.set_master_mute = adev_set_master_mute;
7472 adev->device.get_master_mute = adev_get_master_mute;
7473 adev->device.set_mode = adev_set_mode;
7474 adev->device.set_mic_mute = adev_set_mic_mute;
7475 adev->device.get_mic_mute = adev_get_mic_mute;
7476 adev->device.set_parameters = adev_set_parameters;
7477 adev->device.get_parameters = adev_get_parameters;
7478 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
7479 adev->device.open_output_stream = adev_open_output_stream;
7480 adev->device.close_output_stream = adev_close_output_stream;
7481 adev->device.open_input_stream = adev_open_input_stream;
7482 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307483 adev->device.create_audio_patch = adev_create_audio_patch;
7484 adev->device.release_audio_patch = adev_release_audio_patch;
7485 adev->device.get_audio_port = adev_get_audio_port;
7486 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007487 adev->device.dump = adev_dump;
7488
7489 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007490 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08007491 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007492 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007493 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007494 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08007495 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07007496 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307497 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07007498 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07007499 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007500 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08007501 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08007502 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007503 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05307504 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307505 adev->perf_lock_opts[0] = 0x101;
7506 adev->perf_lock_opts[1] = 0x20E;
7507 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007508 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307509
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007510 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07007511 adev->platform = platform_init(adev);
7512 if (!adev->platform) {
7513 free(adev->snd_dev_ref_cnt);
7514 free(adev);
7515 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7516 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08007517 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307518 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007519 return -EINVAL;
7520 }
Eric Laurentc4aef752013-09-12 17:45:53 -07007521
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307522 if (audio_extn_qaf_is_enabled()) {
7523 ret = audio_extn_qaf_init(adev);
7524 if (ret < 0) {
7525 free(adev);
7526 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7527 *device = NULL;
7528 pthread_mutex_unlock(&adev_init_lock);
7529 pthread_mutex_destroy(&adev->lock);
7530 return ret;
7531 }
7532
7533 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
7534 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
7535 }
7536
Eric Laurentc4aef752013-09-12 17:45:53 -07007537 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
7538 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
7539 if (adev->visualizer_lib == NULL) {
7540 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
7541 } else {
7542 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
7543 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007544 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007545 "visualizer_hal_start_output");
7546 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007547 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007548 "visualizer_hal_stop_output");
7549 }
7550 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05307551 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08007552 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007553 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307554 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007555 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07007556
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007557 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
7558 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
7559 if (adev->offload_effects_lib == NULL) {
7560 ALOGE("%s: DLOPEN failed for %s", __func__,
7561 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7562 } else {
7563 ALOGV("%s: DLOPEN successful for %s", __func__,
7564 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7565 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05307566 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007567 "offload_effects_bundle_hal_start_output");
7568 adev->offload_effects_stop_output =
7569 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
7570 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007571 adev->offload_effects_set_hpx_state =
7572 (int (*)(bool))dlsym(adev->offload_effects_lib,
7573 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05307574 adev->offload_effects_get_parameters =
7575 (void (*)(struct str_parms *, struct str_parms *))
7576 dlsym(adev->offload_effects_lib,
7577 "offload_effects_bundle_get_parameters");
7578 adev->offload_effects_set_parameters =
7579 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
7580 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007581 }
7582 }
7583
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007584 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
7585 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
7586 if (adev->adm_lib == NULL) {
7587 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
7588 } else {
7589 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
7590 adev->adm_init = (adm_init_t)
7591 dlsym(adev->adm_lib, "adm_init");
7592 adev->adm_deinit = (adm_deinit_t)
7593 dlsym(adev->adm_lib, "adm_deinit");
7594 adev->adm_register_input_stream = (adm_register_input_stream_t)
7595 dlsym(adev->adm_lib, "adm_register_input_stream");
7596 adev->adm_register_output_stream = (adm_register_output_stream_t)
7597 dlsym(adev->adm_lib, "adm_register_output_stream");
7598 adev->adm_deregister_stream = (adm_deregister_stream_t)
7599 dlsym(adev->adm_lib, "adm_deregister_stream");
7600 adev->adm_request_focus = (adm_request_focus_t)
7601 dlsym(adev->adm_lib, "adm_request_focus");
7602 adev->adm_abandon_focus = (adm_abandon_focus_t)
7603 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007604 adev->adm_set_config = (adm_set_config_t)
7605 dlsym(adev->adm_lib, "adm_set_config");
7606 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
7607 dlsym(adev->adm_lib, "adm_request_focus_v2");
7608 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
7609 dlsym(adev->adm_lib, "adm_is_noirq_avail");
7610 adev->adm_on_routing_change = (adm_on_routing_change_t)
7611 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007612 }
7613 }
7614
Mingming Yin514a8bc2014-07-29 15:22:21 -07007615 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007616 //initialize this to false for now,
7617 //this will be set to true through set param
7618 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07007619
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07007620 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007621 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007622 adev->dsp_bit_width_enforce_mode =
7623 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007624
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307625 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
7626 &adev->streams_output_cfg_list,
7627 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007628
Kiran Kandi910e1862013-10-29 13:29:42 -07007629 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007630
7631 char value[PROPERTY_VALUE_MAX];
7632 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007633 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007634 trial = atoi(value);
7635 if (period_size_is_plausible_for_low_latency(trial)) {
7636 pcm_config_low_latency.period_size = trial;
7637 pcm_config_low_latency.start_threshold = trial / 4;
7638 pcm_config_low_latency.avail_min = trial / 4;
7639 configured_low_latency_capture_period_size = trial;
7640 }
7641 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007642 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007643 trial = atoi(value);
7644 if (period_size_is_plausible_for_low_latency(trial)) {
7645 configured_low_latency_capture_period_size = trial;
7646 }
7647 }
7648
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007649 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007650 af_period_multiplier = atoi(value);
7651 if (af_period_multiplier < 0)
7652 af_period_multiplier = 2;
7653 else if (af_period_multiplier > 4)
7654 af_period_multiplier = 4;
7655
7656 ALOGV("new period_multiplier = %d", af_period_multiplier);
7657 }
7658
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007659 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007660 pthread_mutex_unlock(&adev_init_lock);
7661
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007662 if (adev->adm_init)
7663 adev->adm_data = adev->adm_init();
7664
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307665 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307666 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007667 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307668
7669 audio_extn_snd_mon_init();
7670 pthread_mutex_lock(&adev->lock);
7671 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
7672 adev->card_status = CARD_STATUS_ONLINE;
7673 pthread_mutex_unlock(&adev->lock);
7674 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307675 /* Allocate memory for Device config params */
7676 adev->device_cfg_params = (struct audio_device_config_param*)
7677 calloc(platform_get_max_codec_backend(),
7678 sizeof(struct audio_device_config_param));
7679 if (adev->device_cfg_params == NULL)
7680 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307681
Eric Laurent994a6932013-07-17 11:51:42 -07007682 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007683 return 0;
7684}
7685
7686static struct hw_module_methods_t hal_module_methods = {
7687 .open = adev_open,
7688};
7689
7690struct audio_module HAL_MODULE_INFO_SYM = {
7691 .common = {
7692 .tag = HARDWARE_MODULE_TAG,
7693 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
7694 .hal_api_version = HARDWARE_HAL_API_VERSION,
7695 .id = AUDIO_HARDWARE_MODULE_ID,
7696 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08007697 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007698 .methods = &hal_module_methods,
7699 },
7700};