blob: 640c5f5aad402f22f48e6b227283a47c51563e9d [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05302 * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070066#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070068#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053077#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080080#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080081
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053082#ifdef DYNAMIC_LOG_ENABLED
83#include <log_xml_parser.h>
84#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
85#include <log_utils.h>
86#endif
87
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053089/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
90#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuriebe78a72018-10-04 18:23:46 -070092#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070093#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053094#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070095
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070096#define PROXY_OPEN_RETRY_COUNT 100
97#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080098
Mingming Yin08c7e312015-03-16 18:10:58 -070099#ifdef USE_LL_AS_PRIMARY_OUTPUT
100#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
101#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
102#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800103#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700104#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
105#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800106
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700107#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700108#define DEFAULT_VOIP_BUF_DURATION_MS 20
109#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
110#define DEFAULT_VOIP_SAMP_RATE 48000
111
112#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
113
114struct pcm_config default_pcm_config_voip_copp = {
115 .channels = 1,
116 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
117 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
118 .period_count = 2,
119 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800120 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
121 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700122};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700123
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700124#define MIN_CHANNEL_COUNT 1
125#define DEFAULT_CHANNEL_COUNT 2
126#define MAX_HIFI_CHANNEL_COUNT 8
127
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700128static unsigned int configured_low_latency_capture_period_size =
129 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
130
Haynes Mathew George16081042017-05-31 17:16:49 -0700131#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
132#define MMAP_PERIOD_COUNT_MIN 32
133#define MMAP_PERIOD_COUNT_MAX 512
134#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
135
Eric Laurentb23d5282013-05-14 15:27:20 -0700136struct pcm_config pcm_config_deep_buffer = {
137 .channels = 2,
138 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
139 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
140 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
141 .format = PCM_FORMAT_S16_LE,
142 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
143 .stop_threshold = INT_MAX,
144 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
145};
146
147struct pcm_config pcm_config_low_latency = {
148 .channels = 2,
149 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
150 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
151 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
152 .format = PCM_FORMAT_S16_LE,
153 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
154 .stop_threshold = INT_MAX,
155 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
156};
157
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700158static int af_period_multiplier = 4;
159struct pcm_config pcm_config_rt = {
160 .channels = 2,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = ULL_PERIOD_SIZE, //1 ms
163 .period_count = 512, //=> buffer size is 512ms
164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
166 .stop_threshold = INT_MAX,
167 .silence_threshold = 0,
168 .silence_size = 0,
169 .avail_min = ULL_PERIOD_SIZE, //1 ms
170};
171
Eric Laurentb23d5282013-05-14 15:27:20 -0700172struct pcm_config pcm_config_hdmi_multi = {
173 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
174 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
175 .period_size = HDMI_MULTI_PERIOD_SIZE,
176 .period_count = HDMI_MULTI_PERIOD_COUNT,
177 .format = PCM_FORMAT_S16_LE,
178 .start_threshold = 0,
179 .stop_threshold = INT_MAX,
180 .avail_min = 0,
181};
182
Haynes Mathew George16081042017-05-31 17:16:49 -0700183struct pcm_config pcm_config_mmap_playback = {
184 .channels = 2,
185 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
186 .period_size = MMAP_PERIOD_SIZE,
187 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
188 .format = PCM_FORMAT_S16_LE,
189 .start_threshold = MMAP_PERIOD_SIZE*8,
190 .stop_threshold = INT32_MAX,
191 .silence_threshold = 0,
192 .silence_size = 0,
193 .avail_min = MMAP_PERIOD_SIZE, //1 ms
194};
195
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700196struct pcm_config pcm_config_hifi = {
197 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
198 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
199 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
200 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
201 .format = PCM_FORMAT_S24_3LE,
202 .start_threshold = 0,
203 .stop_threshold = INT_MAX,
204 .avail_min = 0,
205};
206
Eric Laurentb23d5282013-05-14 15:27:20 -0700207struct pcm_config pcm_config_audio_capture = {
208 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700209 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
210 .format = PCM_FORMAT_S16_LE,
211};
212
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700213struct pcm_config pcm_config_audio_capture_rt = {
214 .channels = 2,
215 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
216 .period_size = ULL_PERIOD_SIZE,
217 .period_count = 512,
218 .format = PCM_FORMAT_S16_LE,
219 .start_threshold = 0,
220 .stop_threshold = INT_MAX,
221 .silence_threshold = 0,
222 .silence_size = 0,
223 .avail_min = ULL_PERIOD_SIZE, //1 ms
224};
225
Haynes Mathew George16081042017-05-31 17:16:49 -0700226struct pcm_config pcm_config_mmap_capture = {
227 .channels = 2,
228 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
229 .period_size = MMAP_PERIOD_SIZE,
230 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
231 .format = PCM_FORMAT_S16_LE,
232 .start_threshold = 0,
233 .stop_threshold = INT_MAX,
234 .silence_threshold = 0,
235 .silence_size = 0,
236 .avail_min = MMAP_PERIOD_SIZE, //1 ms
237};
238
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700239#define AFE_PROXY_CHANNEL_COUNT 2
240#define AFE_PROXY_SAMPLING_RATE 48000
241
242#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
243#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
244
245struct pcm_config pcm_config_afe_proxy_playback = {
246 .channels = AFE_PROXY_CHANNEL_COUNT,
247 .rate = AFE_PROXY_SAMPLING_RATE,
248 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
249 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
250 .format = PCM_FORMAT_S16_LE,
251 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
252 .stop_threshold = INT_MAX,
253 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
254};
255
256#define AFE_PROXY_RECORD_PERIOD_SIZE 768
257#define AFE_PROXY_RECORD_PERIOD_COUNT 4
258
259struct pcm_config pcm_config_afe_proxy_record = {
260 .channels = AFE_PROXY_CHANNEL_COUNT,
261 .rate = AFE_PROXY_SAMPLING_RATE,
262 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
263 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
264 .format = PCM_FORMAT_S16_LE,
265 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
266 .stop_threshold = INT_MAX,
267 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
268};
269
Ashish Jainf1eaa582016-05-23 20:54:24 +0530270#define AUDIO_MAX_PCM_FORMATS 7
271
272const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
273 [AUDIO_FORMAT_DEFAULT] = 0,
274 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
275 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
276 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
277 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
278 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
279 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
280};
281
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800282const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700283 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
284 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700285 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
286 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700287 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700288 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700289 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
290 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
291 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
292 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
293 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
294 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
295 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
296 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700297 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
298 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700299 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700300
Eric Laurentb23d5282013-05-14 15:27:20 -0700301 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700302 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530303 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
304 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
305 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530306 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
307 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700308 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700309 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700310 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700311 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700312
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800313 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800314 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700315 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700316
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700317 [USECASE_VOICE2_CALL] = "voice2-call",
318 [USECASE_VOLTE_CALL] = "volte-call",
319 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800320 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800321 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
322 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800323 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700324 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
325 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
326 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800327 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
328 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
329 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
330
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700331 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
332 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700333 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
334 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700335
336 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
337 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530338 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700339
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530340 /* Transcode loopback cases */
341 [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700342
343 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
344 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530345 /* For Interactive Audio Streams */
346 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
347 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
348 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
349 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
350 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
351 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
352 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
353 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700354
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800355 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
356
357 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback"
Eric Laurentb23d5282013-05-14 15:27:20 -0700358};
359
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700360static const audio_usecase_t offload_usecases[] = {
361 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700362 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
363 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
364 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
365 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
366 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
367 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
368 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
369 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700370};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800371
Varun Balaraje49253e2017-07-06 19:48:56 +0530372static const audio_usecase_t interactive_usecases[] = {
373 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
374 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
375 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
376 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
377 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
378 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
379 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
380 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
381};
382
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800383#define STRING_TO_ENUM(string) { #string, string }
384
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800385struct string_to_enum {
386 const char *name;
387 uint32_t value;
388};
389
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700390static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800391 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800392 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
393 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
394 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700395 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800396 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
397 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800398 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700399 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
400 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
401 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
402 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
403 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
404 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
405 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
406 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
407 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
408 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
409 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800410};
411
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700412static const struct string_to_enum formats_name_to_enum_table[] = {
413 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
414 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
415 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700416 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
417 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
418 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700419 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800420 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
421 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700422 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800423};
424
425//list of all supported sample rates by HDMI specification.
426static const int out_hdmi_sample_rates[] = {
427 32000, 44100, 48000, 88200, 96000, 176400, 192000,
428};
429
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700430static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800431 STRING_TO_ENUM(32000),
432 STRING_TO_ENUM(44100),
433 STRING_TO_ENUM(48000),
434 STRING_TO_ENUM(88200),
435 STRING_TO_ENUM(96000),
436 STRING_TO_ENUM(176400),
437 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700438};
439
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700440static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700441static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700442static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700443//cache last MBDRC cal step level
444static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700445
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530446static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
447static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuriebe78a72018-10-04 18:23:46 -0700448static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800449static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530450
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700451static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
452 int flags __unused)
453{
454 int dir = 0;
455 switch (uc_id) {
456 case USECASE_AUDIO_RECORD_LOW_LATENCY:
457 dir = 1;
458 case USECASE_AUDIO_PLAYBACK_ULL:
459 break;
460 default:
461 return false;
462 }
463
464 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
465 PCM_PLAYBACK : PCM_CAPTURE);
466 if (adev->adm_is_noirq_avail)
467 return adev->adm_is_noirq_avail(adev->adm_data,
468 adev->snd_card, dev_id, dir);
469 return false;
470}
471
472static void register_out_stream(struct stream_out *out)
473{
474 struct audio_device *adev = out->dev;
475 if (is_offload_usecase(out->usecase) ||
476 !adev->adm_register_output_stream)
477 return;
478
479 // register stream first for backward compatibility
480 adev->adm_register_output_stream(adev->adm_data,
481 out->handle,
482 out->flags);
483
484 if (!adev->adm_set_config)
485 return;
486
487 if (out->realtime)
488 adev->adm_set_config(adev->adm_data,
489 out->handle,
490 out->pcm, &out->config);
491}
492
493static void register_in_stream(struct stream_in *in)
494{
495 struct audio_device *adev = in->dev;
496 if (!adev->adm_register_input_stream)
497 return;
498
499 adev->adm_register_input_stream(adev->adm_data,
500 in->capture_handle,
501 in->flags);
502
503 if (!adev->adm_set_config)
504 return;
505
506 if (in->realtime)
507 adev->adm_set_config(adev->adm_data,
508 in->capture_handle,
509 in->pcm,
510 &in->config);
511}
512
513static void request_out_focus(struct stream_out *out, long ns)
514{
515 struct audio_device *adev = out->dev;
516
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700517 if (adev->adm_request_focus_v2)
518 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
519 else if (adev->adm_request_focus)
520 adev->adm_request_focus(adev->adm_data, out->handle);
521}
522
523static void request_in_focus(struct stream_in *in, long ns)
524{
525 struct audio_device *adev = in->dev;
526
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700527 if (adev->adm_request_focus_v2)
528 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
529 else if (adev->adm_request_focus)
530 adev->adm_request_focus(adev->adm_data, in->capture_handle);
531}
532
533static void release_out_focus(struct stream_out *out)
534{
535 struct audio_device *adev = out->dev;
536
537 if (adev->adm_abandon_focus)
538 adev->adm_abandon_focus(adev->adm_data, out->handle);
539}
540
541static void release_in_focus(struct stream_in *in)
542{
543 struct audio_device *adev = in->dev;
544 if (adev->adm_abandon_focus)
545 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
546}
547
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530548static int parse_snd_card_status(struct str_parms *parms, int *card,
549 card_status_t *status)
550{
551 char value[32]={0};
552 char state[32]={0};
553
554 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
555 if (ret < 0)
556 return -1;
557
558 // sscanf should be okay as value is of max length 32.
559 // same as sizeof state.
560 if (sscanf(value, "%d,%s", card, state) < 2)
561 return -1;
562
563 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
564 CARD_STATUS_OFFLINE;
565 return 0;
566}
567
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700568static inline void adjust_frames_for_device_delay(struct stream_out *out,
569 uint32_t *dsp_frames) {
570 // Adjustment accounts for A2dp encoder latency with offload usecases
571 // Note: Encoder latency is returned in ms.
572 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
573 unsigned long offset =
574 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
575 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
576 }
577}
578
vivek mehtaa76401a2015-04-24 14:12:15 -0700579__attribute__ ((visibility ("default")))
580bool audio_hw_send_gain_dep_calibration(int level) {
581 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700582 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700583
584 pthread_mutex_lock(&adev_init_lock);
585
586 if (adev != NULL && adev->platform != NULL) {
587 pthread_mutex_lock(&adev->lock);
588 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700589
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530590 // cache level info for any of the use case which
591 // was not started.
592 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700593
vivek mehtaa76401a2015-04-24 14:12:15 -0700594 pthread_mutex_unlock(&adev->lock);
595 } else {
596 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
597 }
598
599 pthread_mutex_unlock(&adev_init_lock);
600
601 return ret_val;
602}
603
Ashish Jain5106d362016-05-11 19:23:33 +0530604static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
605{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800606 bool gapless_enabled = false;
607 const char *mixer_ctl_name = "Compress Gapless Playback";
608 struct mixer_ctl *ctl;
609
610 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700611 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530612
613 /*Disable gapless if its AV playback*/
614 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800615
616 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
617 if (!ctl) {
618 ALOGE("%s: Could not get ctl for mixer cmd - %s",
619 __func__, mixer_ctl_name);
620 return -EINVAL;
621 }
622
623 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
624 ALOGE("%s: Could not set gapless mode %d",
625 __func__, gapless_enabled);
626 return -EINVAL;
627 }
628 return 0;
629}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700630
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700631__attribute__ ((visibility ("default")))
632int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
633 int table_size) {
634 int ret_val = 0;
635 ALOGV("%s: enter ... ", __func__);
636
637 pthread_mutex_lock(&adev_init_lock);
638 if (adev == NULL) {
639 ALOGW("%s: adev is NULL .... ", __func__);
640 goto done;
641 }
642
643 pthread_mutex_lock(&adev->lock);
644 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
645 pthread_mutex_unlock(&adev->lock);
646done:
647 pthread_mutex_unlock(&adev_init_lock);
648 ALOGV("%s: exit ... ", __func__);
649 return ret_val;
650}
651
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700652static bool is_supported_format(audio_format_t format)
653{
Eric Laurent86e17132013-09-12 17:49:30 -0700654 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530655 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530656 format == AUDIO_FORMAT_AAC_LC ||
657 format == AUDIO_FORMAT_AAC_HE_V1 ||
658 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530659 format == AUDIO_FORMAT_AAC_ADTS_LC ||
660 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
661 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530662 format == AUDIO_FORMAT_AAC_LATM_LC ||
663 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
664 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530665 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
666 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530667 format == AUDIO_FORMAT_PCM_FLOAT ||
668 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700669 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530670 format == AUDIO_FORMAT_AC3 ||
671 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700672 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530673 format == AUDIO_FORMAT_DTS ||
674 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800675 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530676 format == AUDIO_FORMAT_ALAC ||
677 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530678 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530679 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800680 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530681 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700682 format == AUDIO_FORMAT_APTX ||
683 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800684 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700685
686 return false;
687}
688
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700689static inline bool is_mmap_usecase(audio_usecase_t uc_id)
690{
691 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
692 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
693}
694
Avinash Vaish71a8b972014-07-24 15:36:33 +0530695static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
696 struct audio_usecase *uc_info)
697{
698 struct listnode *node;
699 struct audio_usecase *usecase;
700
701 if (uc_info == NULL)
702 return -EINVAL;
703
704 /* Re-route all voice usecases on the shared backend other than the
705 specified usecase to new snd devices */
706 list_for_each(node, &adev->usecase_list) {
707 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800708 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530709 enable_audio_route(adev, usecase);
710 }
711 return 0;
712}
713
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530714static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530715{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530716 ALOGV("%s", __func__);
717 audio_route_apply_and_update_path(adev->audio_route,
718 "asrc-mode");
719 adev->asrc_mode_enabled = true;
720}
721
722static void disable_asrc_mode(struct audio_device *adev)
723{
724 ALOGV("%s", __func__);
725 audio_route_reset_and_update_path(adev->audio_route,
726 "asrc-mode");
727 adev->asrc_mode_enabled = false;
728}
729
730/*
731 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
732 * 44.1 or Native DSD backends are enabled for any of current use case.
733 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
734 * - Disable current mix path use case(Headphone backend) and re-enable it with
735 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
736 * e.g. Naitve DSD or Headphone 44.1 -> + 48
737 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530738static void check_and_set_asrc_mode(struct audio_device *adev,
739 struct audio_usecase *uc_info,
740 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530741{
742 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530743 int i, num_new_devices = 0;
744 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
745 /*
746 *Split snd device for new combo use case
747 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
748 */
749 if (platform_split_snd_device(adev->platform,
750 snd_device,
751 &num_new_devices,
752 split_new_snd_devices) == 0) {
753 for (i = 0; i < num_new_devices; i++)
754 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
755 } else {
756 int new_backend_idx = platform_get_backend_index(snd_device);
757 if (((new_backend_idx == HEADPHONE_BACKEND) ||
758 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
759 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
760 !adev->asrc_mode_enabled) {
761 struct listnode *node = NULL;
762 struct audio_usecase *uc = NULL;
763 struct stream_out *curr_out = NULL;
764 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
765 int i, num_devices, ret = 0;
766 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530767
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530768 list_for_each(node, &adev->usecase_list) {
769 uc = node_to_item(node, struct audio_usecase, list);
770 curr_out = (struct stream_out*) uc->stream.out;
771 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
772 /*
773 *Split snd device for existing combo use case
774 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
775 */
776 ret = platform_split_snd_device(adev->platform,
777 uc->out_snd_device,
778 &num_devices,
779 split_snd_devices);
780 if (ret < 0 || num_devices == 0) {
781 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
782 split_snd_devices[0] = uc->out_snd_device;
783 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800784 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530785 for (i = 0; i < num_devices; i++) {
786 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
787 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
788 if((new_backend_idx == HEADPHONE_BACKEND) &&
789 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
790 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
791 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
792 __func__);
793 enable_asrc_mode(adev);
794 break;
795 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
796 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
797 (usecase_backend_idx == HEADPHONE_BACKEND)) {
798 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
799 __func__);
800 disable_audio_route(adev, uc);
801 disable_snd_device(adev, uc->out_snd_device);
802 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
803 if (new_backend_idx == DSD_NATIVE_BACKEND)
804 audio_route_apply_and_update_path(adev->audio_route,
805 "hph-true-highquality-mode");
806 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
807 (curr_out->bit_width >= 24))
808 audio_route_apply_and_update_path(adev->audio_route,
809 "hph-highquality-mode");
810 enable_asrc_mode(adev);
811 enable_snd_device(adev, uc->out_snd_device);
812 enable_audio_route(adev, uc);
813 break;
814 }
815 }
816 // reset split devices count
817 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800818 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530819 if (adev->asrc_mode_enabled)
820 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530821 }
822 }
823 }
824}
825
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700826#ifdef DYNAMIC_ECNS_ENABLED
827static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
828 struct audio_effect_config effect_config,
829 unsigned int param_value)
830{
831 char mixer_ctl_name[] = "Audio Effect";
832 struct mixer_ctl *ctl;
833 long set_values[6];
834 struct stream_in *in = adev->active_input;
835
836 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
837 if (!ctl) {
838 ALOGE("%s: Could not get mixer ctl - %s",
839 __func__, mixer_ctl_name);
840 return -EINVAL;
841 }
842
843 set_values[0] = 1; //0:Rx 1:Tx
844 set_values[1] = in->app_type_cfg.app_type;
845 set_values[2] = (long)effect_config.module_id;
846 set_values[3] = (long)effect_config.instance_id;
847 set_values[4] = (long)effect_config.param_id;
848 set_values[5] = param_value;
849
850 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
851
852 return 0;
853
854}
855
856static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
857 int effect_type, unsigned int *param_value)
858{
859 int ret = 0;
860 struct audio_effect_config other_effect_config;
861 struct audio_usecase *usecase = NULL;
862 struct stream_in *in = adev->active_input;
863
864 usecase = get_usecase_from_list(adev, in->usecase);
865 if (!usecase)
866 return -EINVAL;
867
868 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
869 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
870 if (ret < 0) {
871 ALOGE("%s Failed to get effect params %d", __func__, ret);
872 return ret;
873 }
874
875 if (module_id == other_effect_config.module_id) {
876 //Same module id for AEC/NS. Values need to be combined
877 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
878 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
879 *param_value |= other_effect_config.param_value;
880 }
881 }
882
883 return ret;
884}
885
886static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
887{
888 struct audio_effect_config effect_config;
889 struct audio_usecase *usecase = NULL;
890 int ret = 0;
891 unsigned int param_value = 0;
892 struct stream_in *in = adev->active_input;
893
894 if (!in) {
895 ALOGE("%s: Invalid input stream", __func__);
896 return -EINVAL;
897 }
898
899 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
900
901 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800902 if (usecase == NULL) {
903 ALOGE("%s: Could not find the usecase (%d) in the list",
904 __func__, in->usecase);
905 return -EINVAL;
906 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700907
908 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
909 if (ret < 0) {
910 ALOGE("%s Failed to get module id %d", __func__, ret);
911 return ret;
912 }
913 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
914 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
915
916 if(enable)
917 param_value = effect_config.param_value;
918
919 /*Special handling for AEC & NS effects Param values need to be
920 updated if module ids are same*/
921
922 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
923 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
924 if (ret < 0)
925 return ret;
926 }
927
928 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
929
930 return ret;
931}
932
933static void check_and_enable_effect(struct audio_device *adev)
934{
935
936 if (adev->active_input->enable_aec) {
937 enable_disable_effect(adev, EFFECT_AEC, true);
938 }
939
940 if (adev->active_input->enable_ns &&
941 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
942 enable_disable_effect(adev, EFFECT_NS, true);
943 }
944}
945#else
946#define enable_disable_effect(x, y, z) ENOSYS
947#define check_and_enable_effect(x) ENOSYS
948#endif
949
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700950int pcm_ioctl(struct pcm *pcm, int request, ...)
951{
952 va_list ap;
953 void * arg;
954 int pcm_fd = *(int*)pcm;
955
956 va_start(ap, request);
957 arg = va_arg(ap, void *);
958 va_end(ap);
959
960 return ioctl(pcm_fd, request, arg);
961}
962
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700963int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700964 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800965{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700966 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700967 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530968 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800969
970 if (usecase == NULL)
971 return -EINVAL;
972
973 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
974
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800975 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700976 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800977 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700978 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800979
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800980#ifdef DS1_DOLBY_DAP_ENABLED
981 audio_extn_dolby_set_dmid(adev);
982 audio_extn_dolby_set_endpoint(adev);
983#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700984 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700985 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530986 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700987 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530988 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530989 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
990 out = usecase->stream.out;
991 if (out && out->compr)
992 audio_extn_utils_compress_set_clk_rec_mode(usecase);
993 }
994
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800995 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700996 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700997 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700998 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800999 ALOGV("%s: exit", __func__);
1000 return 0;
1001}
1002
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001003int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001004 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001005{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001006 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001007 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001008
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301009 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001010 return -EINVAL;
1011
1012 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001013 if (usecase->type == PCM_CAPTURE)
1014 snd_device = usecase->in_snd_device;
1015 else
1016 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001017 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001018 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001019 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001020 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001021 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301022 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001023 ALOGV("%s: exit", __func__);
1024 return 0;
1025}
1026
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001027int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001028 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001029{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301030 int i, num_devices = 0;
1031 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001032 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1033
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001034 if (snd_device < SND_DEVICE_MIN ||
1035 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001036 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001037 return -EINVAL;
1038 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001039
1040 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001041
1042 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
1043 ALOGE("%s: Invalid sound device returned", __func__);
1044 return -EINVAL;
1045 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001046 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -07001047 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001048 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049 return 0;
1050 }
1051
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301052
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001053 if (audio_extn_spkr_prot_is_enabled())
1054 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001055
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001056 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1057 audio_extn_spkr_prot_is_enabled()) {
1058 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001059 adev->snd_dev_ref_cnt[snd_device]--;
1060 return -EINVAL;
1061 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001062 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001063 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001064 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001065 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001066 return -EINVAL;
1067 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001068 } else if (platform_split_snd_device(adev->platform,
1069 snd_device,
1070 &num_devices,
1071 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301072 for (i = 0; i < num_devices; i++) {
1073 enable_snd_device(adev, new_snd_devices[i]);
1074 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001075 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001076 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301077
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301078
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301079 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1080 (audio_extn_a2dp_start_playback() < 0)) {
1081 ALOGE(" fail to configure A2dp control path ");
1082 return -EINVAL;
1083 }
1084
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001085 /* due to the possibility of calibration overwrite between listen
1086 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001087 audio_extn_sound_trigger_update_device_status(snd_device,
1088 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301089 audio_extn_listen_update_device_status(snd_device,
1090 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001091 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001092 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001093 audio_extn_sound_trigger_update_device_status(snd_device,
1094 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301095 audio_extn_listen_update_device_status(snd_device,
1096 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001097 return -EINVAL;
1098 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001099 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001100 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301101
1102 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1103 !adev->native_playback_enabled &&
1104 audio_is_true_native_stream_active(adev)) {
1105 ALOGD("%s: %d: napb: enabling native mode in hardware",
1106 __func__, __LINE__);
1107 audio_route_apply_and_update_path(adev->audio_route,
1108 "true-native-mode");
1109 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301110 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001111 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1112 (audio_extn_ffv_get_stream() == adev->active_input)) {
1113 ALOGD("%s: init ec ref loopback", __func__);
1114 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1115 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001116 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117 return 0;
1118}
1119
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001120int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001121 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001122{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301123 int i, num_devices = 0;
1124 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001125 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1126
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001127 if (snd_device < SND_DEVICE_MIN ||
1128 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001129 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001130 return -EINVAL;
1131 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001132 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1133 ALOGE("%s: device ref cnt is already 0", __func__);
1134 return -EINVAL;
1135 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001136
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001138
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001139 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1140 ALOGE("%s: Invalid sound device returned", __func__);
1141 return -EINVAL;
1142 }
1143
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001144 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001145 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301146
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001147 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1148 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001149 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001150
1151 // when speaker device is disabled, reset swap.
1152 // will be renabled on usecase start
1153 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001154 } else if (platform_split_snd_device(adev->platform,
1155 snd_device,
1156 &num_devices,
1157 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301158 for (i = 0; i < num_devices; i++) {
1159 disable_snd_device(adev, new_snd_devices[i]);
1160 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001161 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001162 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001163 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001164
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301165 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1166 audio_extn_a2dp_stop_playback();
1167
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001168 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301169 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301170 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1171 adev->native_playback_enabled) {
1172 ALOGD("%s: %d: napb: disabling native mode in hardware",
1173 __func__, __LINE__);
1174 audio_route_reset_and_update_path(adev->audio_route,
1175 "true-native-mode");
1176 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301177 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1178 adev->asrc_mode_enabled) {
1179 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301180 disable_asrc_mode(adev);
1181 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301182 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001183 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1184 (audio_extn_ffv_get_stream() == adev->active_input)) {
1185 ALOGD("%s: deinit ec ref loopback", __func__);
1186 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1187 }
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001188 audio_extn_utils_release_snd_device(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001189 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001191 return 0;
1192}
1193
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001194/*
1195 legend:
1196 uc - existing usecase
1197 new_uc - new usecase
1198 d1, d11, d2 - SND_DEVICE enums
1199 a1, a2 - corresponding ANDROID device enums
1200 B1, B2 - backend strings
1201
1202case 1
1203 uc->dev d1 (a1) B1
1204 new_uc->dev d1 (a1), d2 (a2) B1, B2
1205
1206 resolution: disable and enable uc->dev on d1
1207
1208case 2
1209 uc->dev d1 (a1) B1
1210 new_uc->dev d11 (a1) B1
1211
1212 resolution: need to switch uc since d1 and d11 are related
1213 (e.g. speaker and voice-speaker)
1214 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1215
1216case 3
1217 uc->dev d1 (a1) B1
1218 new_uc->dev d2 (a2) B2
1219
1220 resolution: no need to switch uc
1221
1222case 4
1223 uc->dev d1 (a1) B1
1224 new_uc->dev d2 (a2) B1
1225
1226 resolution: disable enable uc-dev on d2 since backends match
1227 we cannot enable two streams on two different devices if they
1228 share the same backend. e.g. if offload is on speaker device using
1229 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1230 using the same backend, offload must also be switched to voice-handset.
1231
1232case 5
1233 uc->dev d1 (a1) B1
1234 new_uc->dev d1 (a1), d2 (a2) B1
1235
1236 resolution: disable enable uc-dev on d2 since backends match
1237 we cannot enable two streams on two different devices if they
1238 share the same backend.
1239
1240case 6
1241 uc->dev d1 (a1) B1
1242 new_uc->dev d2 (a1) B2
1243
1244 resolution: no need to switch
1245
1246case 7
1247 uc->dev d1 (a1), d2 (a2) B1, B2
1248 new_uc->dev d1 (a1) B1
1249
1250 resolution: no need to switch
1251
Zhou Song4ba65882018-07-09 14:48:07 +08001252case 8
1253 uc->dev d1 (a1) B1
1254 new_uc->dev d11 (a1), d2 (a2) B1, B2
1255 resolution: compared to case 1, for this case, d1 and d11 are related
1256 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001257*/
1258static snd_device_t derive_playback_snd_device(void * platform,
1259 struct audio_usecase *uc,
1260 struct audio_usecase *new_uc,
1261 snd_device_t new_snd_device)
1262{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301263 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001264
1265 snd_device_t d1 = uc->out_snd_device;
1266 snd_device_t d2 = new_snd_device;
1267
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301268 switch (uc->type) {
1269 case TRANSCODE_LOOPBACK :
1270 a1 = uc->stream.inout->out_config.devices;
1271 a2 = new_uc->stream.inout->out_config.devices;
1272 break;
1273 default :
1274 a1 = uc->stream.out->devices;
1275 a2 = new_uc->stream.out->devices;
1276 break;
1277 }
1278
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001279 // Treat as a special case when a1 and a2 are not disjoint
1280 if ((a1 != a2) && (a1 & a2)) {
1281 snd_device_t d3[2];
1282 int num_devices = 0;
1283 int ret = platform_split_snd_device(platform,
1284 popcount(a1) > 1 ? d1 : d2,
1285 &num_devices,
1286 d3);
1287 if (ret < 0) {
1288 if (ret != -ENOSYS) {
1289 ALOGW("%s failed to split snd_device %d",
1290 __func__,
1291 popcount(a1) > 1 ? d1 : d2);
1292 }
1293 goto end;
1294 }
1295
1296 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1297 // But if it does happen, we need to give priority to d2 if
1298 // the combo devices active on the existing usecase share a backend.
1299 // This is because we cannot have a usecase active on a combo device
1300 // and a new usecase requests one device in this combo pair.
1301 if (platform_check_backends_match(d3[0], d3[1])) {
1302 return d2; // case 5
1303 } else {
Zhou Song671be042018-08-27 15:33:52 +08001304 // check if d1 is related to any of d3's OR
1305 // old uc is combo device but new_uc is one of the combo device
1306 if (d1 == d3[0] || d1 == d3[1] || popcount(a1) > 1)
1307 return d1; // case 1, 7
Zhou Song4ba65882018-07-09 14:48:07 +08001308 else
1309 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001310 }
1311 } else {
1312 if (platform_check_backends_match(d1, d2)) {
1313 return d2; // case 2, 4
1314 } else {
1315 return d1; // case 6, 3
1316 }
1317 }
1318
1319end:
1320 return d2; // return whatever was calculated before.
1321}
1322
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001323static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301324 struct audio_usecase *uc_info,
1325 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001326{
1327 struct listnode *node;
1328 struct audio_usecase *usecase;
1329 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301330 snd_device_t uc_derive_snd_device;
1331 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001332 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1333 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001334 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301335 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001336 /*
1337 * This function is to make sure that all the usecases that are active on
1338 * the hardware codec backend are always routed to any one device that is
1339 * handled by the hardware codec.
1340 * For example, if low-latency and deep-buffer usecases are currently active
1341 * on speaker and out_set_parameters(headset) is received on low-latency
1342 * output, then we have to make sure deep-buffer is also switched to headset,
1343 * because of the limitation that both the devices cannot be enabled
1344 * at the same time as they share the same backend.
1345 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001346 /*
1347 * This call is to check if we need to force routing for a particular stream
1348 * If there is a backend configuration change for the device when a
1349 * new stream starts, then ADM needs to be closed and re-opened with the new
1350 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001351 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001352 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001353 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1354 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301355 /* For a2dp device reconfigure all active sessions
1356 * with new AFE encoder format based on a2dp state
1357 */
1358 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1359 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1360 audio_extn_a2dp_is_force_device_switch()) {
1361 force_routing = true;
1362 force_restart_session = true;
1363 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301364 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1365
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001366 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001367 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001368 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001369 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1370 switch_device[i] = false;
1371
1372 list_for_each(node, &adev->usecase_list) {
1373 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001374
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301375 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1376 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301377 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301378 platform_get_snd_device_name(usecase->out_snd_device),
1379 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301380 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1381 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1382 usecase, uc_info, snd_device);
1383 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1384 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1385 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1386 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001387 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301388 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1389 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1390 ((force_restart_session) ||
1391 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301392 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1393 __func__, use_case_table[usecase->id],
1394 platform_get_snd_device_name(usecase->out_snd_device));
1395 disable_audio_route(adev, usecase);
1396 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301397 /* Enable existing usecase on derived playback device */
1398 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301399 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301400 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001401 }
1402 }
1403
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301404 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1405 num_uc_to_switch);
1406
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001407 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001408 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001409
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301410 /* Make sure the previous devices to be disabled first and then enable the
1411 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001412 list_for_each(node, &adev->usecase_list) {
1413 usecase = node_to_item(node, struct audio_usecase, list);
1414 if (switch_device[usecase->id]) {
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001415 /* Check if output sound device to be switched can be split and if any
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001416 of the split devices match with derived sound device */
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001417 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1418 &num_devices, split_snd_devices) == 0) {
1419 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1420 if (adev->snd_dev_ref_cnt[usecase->out_snd_device] == 0) {
1421 ALOGD("%s: disabling snd_device(%d)", __func__, usecase->out_snd_device);
1422 for (i = 0; i < num_devices; i++) {
1423 /* Disable devices that do not match with derived sound device */
1424 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1425 disable_snd_device(adev, split_snd_devices[i]);
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001426 }
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001427 audio_extn_utils_release_snd_device(usecase->out_snd_device);
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001428 }
1429 } else {
1430 disable_snd_device(adev, usecase->out_snd_device);
1431 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001432 }
1433 }
1434
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001435 list_for_each(node, &adev->usecase_list) {
1436 usecase = node_to_item(node, struct audio_usecase, list);
1437 if (switch_device[usecase->id]) {
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001438 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1439 &num_devices, split_snd_devices) == 0) {
1440 /* Enable derived sound device only if it does not match with
1441 one of the split sound devices. This is because the matching
1442 sound device was not disabled */
1443 bool should_enable = true;
1444 for (i = 0; i < num_devices; i++) {
1445 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1446 should_enable = false;
1447 break;
1448 }
1449 }
1450 if (should_enable)
1451 enable_snd_device(adev, derive_snd_device[usecase->id]);
1452 } else {
1453 enable_snd_device(adev, derive_snd_device[usecase->id]);
1454 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001455 }
1456 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001457
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001458 /* Re-route all the usecases on the shared backend other than the
1459 specified usecase to new snd devices */
1460 list_for_each(node, &adev->usecase_list) {
1461 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301462 /* Update the out_snd_device only before enabling the audio route */
1463 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301464 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301465 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301466 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301467 use_case_table[usecase->id],
1468 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001469 /* Update voc calibration before enabling VoIP route */
1470 if (usecase->type == VOIP_CALL)
1471 status = platform_switch_voice_call_device_post(adev->platform,
1472 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001473 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301474 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001475 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1476 out_set_voip_volume(&usecase->stream.out->stream,
1477 usecase->stream.out->volume_l,
1478 usecase->stream.out->volume_r);
1479 }
Yidong Huang7939a3b2018-01-23 17:32:30 +08001480 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1481 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1482 if (parms)
1483 audio_extn_fm_set_parameters(adev, parms);
1484 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301485 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001486 }
1487 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001488 }
1489}
1490
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301491static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001492 struct audio_usecase *uc_info,
1493 snd_device_t snd_device)
1494{
1495 struct listnode *node;
1496 struct audio_usecase *usecase;
1497 bool switch_device[AUDIO_USECASE_MAX];
1498 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301499 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001500 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001501
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301502 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1503 snd_device);
1504 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301505
1506 /*
1507 * Make sure out devices is checked against out codec backend device and
1508 * also in devices against in codec backend. Checking out device against in
1509 * codec backend or vice versa causes issues.
1510 */
1511 if (uc_info->type == PCM_CAPTURE)
1512 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001513 /*
1514 * This function is to make sure that all the active capture usecases
1515 * are always routed to the same input sound device.
1516 * For example, if audio-record and voice-call usecases are currently
1517 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1518 * is received for voice call then we have to make sure that audio-record
1519 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1520 * because of the limitation that two devices cannot be enabled
1521 * at the same time if they share the same backend.
1522 */
1523 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1524 switch_device[i] = false;
1525
1526 list_for_each(node, &adev->usecase_list) {
1527 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301528 /*
1529 * TODO: Enhance below condition to handle BT sco/USB multi recording
1530 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001531 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001532 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301533 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301534 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301535 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301536 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001537 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001538 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1539 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001540 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001541 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001542 switch_device[usecase->id] = true;
1543 num_uc_to_switch++;
1544 }
1545 }
1546
1547 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001548 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001549
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301550 /* Make sure the previous devices to be disabled first and then enable the
1551 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001552 list_for_each(node, &adev->usecase_list) {
1553 usecase = node_to_item(node, struct audio_usecase, list);
1554 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001555 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001556 }
1557 }
1558
1559 list_for_each(node, &adev->usecase_list) {
1560 usecase = node_to_item(node, struct audio_usecase, list);
1561 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001562 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001563 }
1564 }
1565
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001566 /* Re-route all the usecases on the shared backend other than the
1567 specified usecase to new snd devices */
1568 list_for_each(node, &adev->usecase_list) {
1569 usecase = node_to_item(node, struct audio_usecase, list);
1570 /* Update the in_snd_device only before enabling the audio route */
1571 if (switch_device[usecase->id] ) {
1572 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001573 if (usecase->type != VOICE_CALL) {
1574 /* Update voc calibration before enabling VoIP route */
1575 if (usecase->type == VOIP_CALL)
1576 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001577 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001578 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301579 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001580 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001581 }
1582 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001583 }
1584}
1585
Mingming Yin3a941d42016-02-17 18:08:05 -08001586static void reset_hdmi_sink_caps(struct stream_out *out) {
1587 int i = 0;
1588
1589 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1590 out->supported_channel_masks[i] = 0;
1591 }
1592 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1593 out->supported_formats[i] = 0;
1594 }
1595 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1596 out->supported_sample_rates[i] = 0;
1597 }
1598}
1599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001600/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001601static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001602{
Mingming Yin3a941d42016-02-17 18:08:05 -08001603 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001604 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001605
Mingming Yin3a941d42016-02-17 18:08:05 -08001606 reset_hdmi_sink_caps(out);
1607
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001608 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001609 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001610 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001611 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001612 }
1613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001614 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001615 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001616 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001617 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001618 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1619 case 6:
1620 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1621 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1622 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1623 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1624 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1625 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626 break;
1627 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001628 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001629 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001630 break;
1631 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001632
1633 // check channel format caps
1634 i = 0;
1635 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1636 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1637 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1638 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1639 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1640 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1641 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1642 }
1643
Ben Romberger1aaaf862017-04-06 17:49:46 -07001644 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1645 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1646 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1647 }
1648
Mingming Yin3a941d42016-02-17 18:08:05 -08001649 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1650 ALOGV(":%s HDMI supports DTS format", __func__);
1651 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1652 }
1653
1654 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1655 ALOGV(":%s HDMI supports DTS HD format", __func__);
1656 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1657 }
1658
Naresh Tanniru928f0862017-04-07 16:44:23 -07001659 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1660 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1661 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1662 }
1663
Mingming Yin3a941d42016-02-17 18:08:05 -08001664
1665 // check sample rate caps
1666 i = 0;
1667 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1668 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1669 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1670 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1671 }
1672 }
1673
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001674 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001675}
1676
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001677static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1678 uint32_t *supported_sample_rates __unused,
1679 uint32_t max_rates __unused)
1680{
1681 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1682 supported_sample_rates,
1683 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301684 ssize_t i = 0;
1685
1686 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001687 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1688 supported_sample_rates[i]);
1689 }
1690 return count;
1691}
1692
1693static inline int read_usb_sup_channel_masks(bool is_playback,
1694 audio_channel_mask_t *supported_channel_masks,
1695 uint32_t max_masks)
1696{
1697 int channels = audio_extn_usb_get_max_channels(is_playback);
1698 int channel_count;
1699 uint32_t num_masks = 0;
1700 if (channels > MAX_HIFI_CHANNEL_COUNT)
1701 channels = MAX_HIFI_CHANNEL_COUNT;
1702
1703 if (is_playback) {
1704 // For playback we never report mono because the framework always outputs stereo
1705 channel_count = DEFAULT_CHANNEL_COUNT;
1706 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1707 // above 2 but we want indexed masks here. So we
1708 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1709 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1710 }
1711 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1712 supported_channel_masks[num_masks++] =
1713 audio_channel_mask_for_index_assignment_from_count(channel_count);
1714 }
1715 } else {
1716 // For capture we report all supported channel masks from 1 channel up.
1717 channel_count = MIN_CHANNEL_COUNT;
1718 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1719 // indexed mask
1720 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1721 supported_channel_masks[num_masks++] =
1722 audio_channel_in_mask_from_count(channel_count);
1723 }
1724 }
1725 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1726 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1727 return num_masks;
1728}
1729
1730static inline int read_usb_sup_formats(bool is_playback __unused,
1731 audio_format_t *supported_formats,
1732 uint32_t max_formats __unused)
1733{
1734 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1735 switch (bitwidth) {
1736 case 24:
1737 // XXX : usb.c returns 24 for s24 and s24_le?
1738 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1739 break;
1740 case 32:
1741 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1742 break;
1743 case 16:
1744 default :
1745 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1746 break;
1747 }
1748 ALOGV("%s: %s supported format %d", __func__,
1749 is_playback ? "P" : "C", bitwidth);
1750 return 1;
1751}
1752
1753static inline int read_usb_sup_params_and_compare(bool is_playback,
1754 audio_format_t *format,
1755 audio_format_t *supported_formats,
1756 uint32_t max_formats,
1757 audio_channel_mask_t *mask,
1758 audio_channel_mask_t *supported_channel_masks,
1759 uint32_t max_masks,
1760 uint32_t *rate,
1761 uint32_t *supported_sample_rates,
1762 uint32_t max_rates) {
1763 int ret = 0;
1764 int num_formats;
1765 int num_masks;
1766 int num_rates;
1767 int i;
1768
1769 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1770 max_formats);
1771 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1772 max_masks);
1773
1774 num_rates = read_usb_sup_sample_rates(is_playback,
1775 supported_sample_rates, max_rates);
1776
1777#define LUT(table, len, what, dflt) \
1778 for (i=0; i<len && (table[i] != what); i++); \
1779 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1780
1781 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1782 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1783 LUT(supported_sample_rates, num_rates, *rate, 0);
1784
1785#undef LUT
1786 return ret < 0 ? -EINVAL : 0; // HACK TBD
1787}
1788
Alexy Josephb1379942016-01-29 15:49:38 -08001789audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001790 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001791{
1792 struct audio_usecase *usecase;
1793 struct listnode *node;
1794
1795 list_for_each(node, &adev->usecase_list) {
1796 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001797 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001798 ALOGV("%s: usecase id %d", __func__, usecase->id);
1799 return usecase->id;
1800 }
1801 }
1802 return USECASE_INVALID;
1803}
1804
Alexy Josephb1379942016-01-29 15:49:38 -08001805struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001806 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001807{
1808 struct audio_usecase *usecase;
1809 struct listnode *node;
1810
1811 list_for_each(node, &adev->usecase_list) {
1812 usecase = node_to_item(node, struct audio_usecase, list);
1813 if (usecase->id == uc_id)
1814 return usecase;
1815 }
1816 return NULL;
1817}
1818
Dhananjay Kumard4833242016-10-06 22:09:12 +05301819struct stream_in *get_next_active_input(const struct audio_device *adev)
1820{
1821 struct audio_usecase *usecase;
1822 struct listnode *node;
1823
1824 list_for_each_reverse(node, &adev->usecase_list) {
1825 usecase = node_to_item(node, struct audio_usecase, list);
1826 if (usecase->type == PCM_CAPTURE)
1827 return usecase->stream.in;
1828 }
1829 return NULL;
1830}
1831
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301832/*
1833 * is a true native playback active
1834 */
1835bool audio_is_true_native_stream_active(struct audio_device *adev)
1836{
1837 bool active = false;
1838 int i = 0;
1839 struct listnode *node;
1840
1841 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1842 ALOGV("%s:napb: not in true mode or non hdphones device",
1843 __func__);
1844 active = false;
1845 goto exit;
1846 }
1847
1848 list_for_each(node, &adev->usecase_list) {
1849 struct audio_usecase *uc;
1850 uc = node_to_item(node, struct audio_usecase, list);
1851 struct stream_out *curr_out =
1852 (struct stream_out*) uc->stream.out;
1853
1854 if (curr_out && PCM_PLAYBACK == uc->type) {
1855 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1856 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1857 uc->id, curr_out->sample_rate,
1858 curr_out->bit_width,
1859 platform_get_snd_device_name(uc->out_snd_device));
1860
1861 if (is_offload_usecase(uc->id) &&
1862 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1863 active = true;
1864 ALOGD("%s:napb:native stream detected", __func__);
1865 }
1866 }
1867 }
1868exit:
1869 return active;
1870}
1871
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001872uint32_t adev_get_dsp_bit_width_enforce_mode()
1873{
1874 if (adev == NULL) {
1875 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1876 return 0;
1877 }
1878 return adev->dsp_bit_width_enforce_mode;
1879}
1880
1881static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1882{
1883 char value[PROPERTY_VALUE_MAX];
1884 int trial;
1885 uint32_t dsp_bit_width_enforce_mode = 0;
1886
1887 if (!mixer) {
1888 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1889 __func__);
1890 return 0;
1891 }
1892
1893 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1894 value, NULL) > 0) {
1895 trial = atoi(value);
1896 switch (trial) {
1897 case 16:
1898 dsp_bit_width_enforce_mode = 16;
1899 break;
1900 case 24:
1901 dsp_bit_width_enforce_mode = 24;
1902 break;
1903 case 32:
1904 dsp_bit_width_enforce_mode = 32;
1905 break;
1906 default:
1907 dsp_bit_width_enforce_mode = 0;
1908 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1909 break;
1910 }
1911 }
1912
1913 return dsp_bit_width_enforce_mode;
1914}
1915
1916static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1917 uint32_t enforce_mode,
1918 bool enable)
1919{
1920 struct mixer_ctl *ctl = NULL;
1921 const char *mixer_ctl_name = "ASM Bit Width";
1922 uint32_t asm_bit_width_mode = 0;
1923
1924 if (enforce_mode == 0) {
1925 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1926 return;
1927 }
1928
1929 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1930 if (!ctl) {
1931 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1932 __func__, mixer_ctl_name);
1933 return;
1934 }
1935
1936 if (enable)
1937 asm_bit_width_mode = enforce_mode;
1938 else
1939 asm_bit_width_mode = 0;
1940
1941 ALOGV("%s DSP bit width feature status is %d width=%d",
1942 __func__, enable, asm_bit_width_mode);
1943 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1944 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1945 asm_bit_width_mode);
1946
1947 return;
1948}
1949
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301950/*
1951 * if native DSD playback active
1952 */
1953bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1954{
1955 bool active = false;
1956 struct listnode *node = NULL;
1957 struct audio_usecase *uc = NULL;
1958 struct stream_out *curr_out = NULL;
1959
1960 list_for_each(node, &adev->usecase_list) {
1961 uc = node_to_item(node, struct audio_usecase, list);
1962 curr_out = (struct stream_out*) uc->stream.out;
1963
1964 if (curr_out && PCM_PLAYBACK == uc->type &&
1965 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1966 active = true;
1967 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301968 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301969 }
1970 }
1971 return active;
1972}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301973
1974static bool force_device_switch(struct audio_usecase *usecase)
1975{
1976 bool ret = false;
1977 bool is_it_true_mode = false;
1978
Zhou Song30f2c3e2018-02-08 14:02:15 +08001979 if (usecase->type == PCM_CAPTURE ||
1980 usecase->type == TRANSCODE_LOOPBACK) {
1981 return false;
1982 }
1983
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001984 if(usecase->stream.out == NULL) {
1985 ALOGE("%s: stream.out is NULL", __func__);
1986 return false;
1987 }
1988
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301989 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001990 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1991 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1992 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301993 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1994 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1995 (!is_it_true_mode && adev->native_playback_enabled)){
1996 ret = true;
1997 ALOGD("napb: time to toggle native mode");
1998 }
1999 }
2000
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302001 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302002 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2003 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002004 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302005 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302006 ALOGD("Force a2dp device switch to update new encoder config");
2007 ret = true;
2008 }
2009
Manish Dewangan671a4202017-08-18 17:30:46 +05302010 if (usecase->stream.out->stream_config_changed) {
2011 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2012 return true;
2013 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302014 return ret;
2015}
2016
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302017bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2018{
2019 bool ret=false;
2020 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2021 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2022 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2023 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2024 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2025 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2026 ret = true;
2027
2028 return ret;
2029}
2030
2031bool is_a2dp_device(snd_device_t out_snd_device)
2032{
2033 bool ret=false;
2034 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2035 ret = true;
2036
2037 return ret;
2038}
2039
2040bool is_bt_soc_on(struct audio_device *adev)
2041{
2042 struct mixer_ctl *ctl;
2043 char *mixer_ctl_name = "BT SOC status";
2044 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2045 bool bt_soc_status = true;
2046 if (!ctl) {
2047 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2048 __func__, mixer_ctl_name);
2049 /*This is to ensure we dont break targets which dont have the kernel change*/
2050 return true;
2051 }
2052 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2053 ALOGD("BT SOC status: %d",bt_soc_status);
2054 return bt_soc_status;
2055}
2056
2057int out_standby_l(struct audio_stream *stream);
2058
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002059int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002061 snd_device_t out_snd_device = SND_DEVICE_NONE;
2062 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002063 struct audio_usecase *usecase = NULL;
2064 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002065 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002066 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302067 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002068 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002069 int status = 0;
Weiyin Jiang5d608082018-02-01 17:24:33 +08002070 audio_devices_t audio_device;
2071 audio_channel_mask_t channel_mask;
2072 int sample_rate;
2073 int acdb_id;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002074
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302075 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2076
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002077 usecase = get_usecase_from_list(adev, uc_id);
2078 if (usecase == NULL) {
2079 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2080 return -EINVAL;
2081 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002082
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002083 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002084 (usecase->type == VOIP_CALL) ||
2085 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302086 if(usecase->stream.out == NULL) {
2087 ALOGE("%s: stream.out is NULL", __func__);
2088 return -EINVAL;
2089 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002090 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002091 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002092 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002093 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302094 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
2095 if (usecase->stream.inout == NULL) {
2096 ALOGE("%s: stream.inout is NULL", __func__);
2097 return -EINVAL;
2098 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302099 stream_out.devices = usecase->stream.inout->out_config.devices;
2100 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2101 stream_out.format = usecase->stream.inout->out_config.format;
2102 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2103 out_snd_device = platform_get_output_snd_device(adev->platform,
2104 &stream_out);
2105 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302106 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002107 } else {
2108 /*
2109 * If the voice call is active, use the sound devices of voice call usecase
2110 * so that it would not result any device switch. All the usecases will
2111 * be switched to new device when select_devices() is called for voice call
2112 * usecase. This is to avoid switching devices for voice call when
2113 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002114 * choose voice call device only if the use case device is
2115 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002116 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002117 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002118 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002119 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002120 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2121 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302122 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2123 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002124 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002125 in_snd_device = vc_usecase->in_snd_device;
2126 out_snd_device = vc_usecase->out_snd_device;
2127 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002128 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002129 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002130 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002131 if ((voip_usecase != NULL) &&
2132 (usecase->type == PCM_PLAYBACK) &&
2133 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002134 out_snd_device_backend_match = platform_check_backends_match(
2135 voip_usecase->out_snd_device,
2136 platform_get_output_snd_device(
2137 adev->platform,
2138 usecase->stream.out));
2139 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002140 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002141 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2142 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002143 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002144 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002145 in_snd_device = voip_usecase->in_snd_device;
2146 out_snd_device = voip_usecase->out_snd_device;
2147 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002148 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002149 hfp_ucid = audio_extn_hfp_get_usecase();
2150 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002151 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002152 in_snd_device = hfp_usecase->in_snd_device;
2153 out_snd_device = hfp_usecase->out_snd_device;
2154 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002155 }
2156 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302157 if (usecase->stream.out == NULL) {
2158 ALOGE("%s: stream.out is NULL", __func__);
2159 return -EINVAL;
2160 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002161 usecase->devices = usecase->stream.out->devices;
2162 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002163 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002164 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002165 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002166 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleiz3ca773f2018-10-12 15:49:35 +08002167 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002168 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2169
2170 if ((usecase->stream.out != NULL &&
2171 voip_usecase != NULL &&
2172 usecase->stream.out->usecase == voip_usecase->id) &&
2173 adev->active_input &&
kunleiz3ca773f2018-10-12 15:49:35 +08002174 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002175 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002176 select_devices(adev, adev->active_input->usecase);
2177 }
2178 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002179 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302180 if (usecase->stream.in == NULL) {
2181 ALOGE("%s: stream.in is NULL", __func__);
2182 return -EINVAL;
2183 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002184 usecase->devices = usecase->stream.in->device;
2185 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002186 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002187 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002188 if (adev->active_input &&
2189 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302190 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002191 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2192 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2193 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2194 out_device = voip_usecase->stream.out->devices;
2195 else if (adev->primary_output && !adev->primary_output->standby)
2196 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002197 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002198 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2199 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002200 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002201 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002202 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002203 }
2204 }
2205
2206 if (out_snd_device == usecase->out_snd_device &&
2207 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302208
2209 if (!force_device_switch(usecase))
2210 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002211 }
2212
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302213 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
2214 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
2215 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2216 return 0;
2217 }
2218
sangwoobc677242013-08-08 16:53:43 +09002219 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07002220 out_snd_device, platform_get_snd_device_name(out_snd_device),
2221 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002222
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223 /*
2224 * Limitation: While in call, to do a device switch we need to disable
2225 * and enable both RX and TX devices though one of them is same as current
2226 * device.
2227 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002228 if ((usecase->type == VOICE_CALL) &&
2229 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2230 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002231 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002232 }
2233
2234 if (((usecase->type == VOICE_CALL) ||
2235 (usecase->type == VOIP_CALL)) &&
2236 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2237 /* Disable sidetone only if voice/voip call already exists */
2238 if (voice_is_call_state_active(adev) ||
2239 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002240 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002241
2242 /* Disable aanc only if voice call exists */
2243 if (voice_is_call_state_active(adev))
2244 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002245 }
2246
Zhou Songc66eb7e2017-08-08 18:29:07 +08002247 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302248 (!audio_extn_a2dp_is_ready())) {
2249 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002250 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302251 }
2252
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002253 /* Disable current sound devices */
2254 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002255 disable_audio_route(adev, usecase);
2256 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257 }
2258
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002259 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002260 disable_audio_route(adev, usecase);
2261 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002262 }
2263
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002264 /* Applicable only on the targets that has external modem.
2265 * New device information should be sent to modem before enabling
2266 * the devices to reduce in-call device switch time.
2267 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002268 if ((usecase->type == VOICE_CALL) &&
2269 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2270 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002271 status = platform_switch_voice_call_enable_device_config(adev->platform,
2272 out_snd_device,
2273 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002274 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002275
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002276 /* Enable new sound devices */
2277 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002278 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302279 if (platform_check_codec_asrc_support(adev->platform))
2280 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002281 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002282 }
2283
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002284 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302285 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002286 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002287 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002288
Avinash Vaish71a8b972014-07-24 15:36:33 +05302289 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002290 status = platform_switch_voice_call_device_post(adev->platform,
2291 out_snd_device,
2292 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302293 enable_audio_route_for_voice_usecases(adev, usecase);
2294 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002295
sangwoo170731f2013-06-08 15:36:36 +09002296 usecase->in_snd_device = in_snd_device;
2297 usecase->out_snd_device = out_snd_device;
2298
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302299 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2300 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302301 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002302 if ((24 == usecase->stream.out->bit_width) &&
2303 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2304 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2305 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2306 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2307 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2308 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2309 /*
2310 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2311 * configured device sample rate, if not update the COPP rate to be equal to the
2312 * device sample rate, else open COPP at stream sample rate
2313 */
2314 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2315 usecase->stream.out->sample_rate,
2316 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302317 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2318 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002319 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2320 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2321 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2322 }
2323
Weiyin Jiang5d608082018-02-01 17:24:33 +08002324 /* Cache stream information to be notified to gef clients */
2325 audio_device = usecase->stream.out->devices;
2326 channel_mask = usecase->stream.out->channel_mask;
2327 sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
2328 acdb_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302329 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002330 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002331
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002332 /* If input stream is already running then effect needs to be
2333 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002334 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2335 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002336 check_and_enable_effect(adev);
2337
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002338 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002339 /* Enable aanc only if voice call exists */
2340 if (voice_is_call_state_active(adev))
2341 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2342
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002343 /* Enable sidetone only if other voice/voip call already exists */
2344 if (voice_is_call_state_active(adev) ||
2345 voice_extn_compress_voip_is_started(adev))
2346 voice_set_sidetone(adev, out_snd_device, true);
2347 }
2348
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002349 /* Applicable only on the targets that has external modem.
2350 * Enable device command should be sent to modem only after
2351 * enabling voice call mixer controls
2352 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002353 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002354 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2355 out_snd_device,
2356 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302357
2358 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2359
2360 if (usecase->type == VOIP_CALL) {
2361 if (adev->active_input != NULL &&
2362 !adev->active_input->standby) {
2363 if (is_bt_soc_on(adev) == false){
2364 ALOGD("BT SCO MIC disconnected while in connection");
2365 if (adev->active_input->pcm != NULL)
2366 pcm_stop(adev->active_input->pcm);
2367 }
2368 }
2369 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2370 && usecase->stream.out->started) {
2371 if (is_bt_soc_on(adev) == false) {
2372 ALOGD("BT SCO/A2DP disconnected while in connection");
2373 out_standby_l(&usecase->stream.out->stream.common);
2374 }
2375 }
2376 } else if ((usecase->stream.out != NULL) &&
2377 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2378 usecase->stream.out->started) {
2379 if (is_bt_soc_on(adev) == false) {
2380 ALOGD("BT SCO/A2dp disconnected while in connection");
2381 out_standby_l(&usecase->stream.out->stream.common);
2382 }
2383 }
2384 }
2385
Weiyin Jiang5d608082018-02-01 17:24:33 +08002386 /* Notify device change info to effect clients registered
2387 * NOTE: device lock has to be unlock temporarily here.
2388 * To the worst case, we notify stale info to clients.
2389 */
2390 if (usecase->type == PCM_PLAYBACK) {
2391 pthread_mutex_unlock(&adev->lock);
2392 audio_extn_gef_notify_device_config(audio_device, channel_mask, sample_rate, acdb_id);
2393 pthread_mutex_lock(&adev->lock);
2394 }
2395
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302396 ALOGD("%s: done",__func__);
2397
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002398 return status;
2399}
2400
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002401static int stop_input_stream(struct stream_in *in)
2402{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302403 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002404 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302405
2406 if (in == NULL) {
2407 ALOGE("%s: stream_in ptr is NULL", __func__);
2408 return -EINVAL;
2409 }
2410
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002411 struct audio_device *adev = in->dev;
2412
Eric Laurent994a6932013-07-17 11:51:42 -07002413 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002414 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415 uc_info = get_usecase_from_list(adev, in->usecase);
2416 if (uc_info == NULL) {
2417 ALOGE("%s: Could not find the usecase (%d) in the list",
2418 __func__, in->usecase);
2419 return -EINVAL;
2420 }
2421
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002422 /* Close in-call recording streams */
2423 voice_check_and_stop_incall_rec_usecase(adev, in);
2424
Eric Laurent150dbfe2013-02-27 14:31:02 -08002425 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002426 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002427
2428 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002429 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002431 list_remove(&uc_info->list);
2432 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002434 adev->active_input = get_next_active_input(adev);
2435
Eric Laurent994a6932013-07-17 11:51:42 -07002436 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437 return ret;
2438}
2439
2440int start_input_stream(struct stream_in *in)
2441{
2442 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002443 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002444 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302445
2446 if (in == NULL) {
2447 ALOGE("%s: stream_in ptr is NULL", __func__);
2448 return -EINVAL;
2449 }
2450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002452 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002453 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002454
Mingming Yin2664a5b2015-09-03 10:53:11 -07002455 if (get_usecase_from_list(adev, usecase) == NULL)
2456 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302457 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2458 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002459
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302460 if (CARD_STATUS_OFFLINE == in->card_status||
2461 CARD_STATUS_OFFLINE == adev->card_status) {
2462 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302463 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302464 goto error_config;
2465 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302466
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302467 if (audio_is_bluetooth_sco_device(in->device)) {
2468 if (!adev->bt_sco_on) {
2469 ALOGE("%s: SCO profile is not ready, return error", __func__);
2470 ret = -EIO;
2471 goto error_config;
2472 }
2473 }
2474
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002475 /* Check if source matches incall recording usecase criteria */
2476 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2477 if (ret)
2478 goto error_config;
2479 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002480 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2481
2482 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2483 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2484 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002485 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002486 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002487
Eric Laurentb23d5282013-05-14 15:27:20 -07002488 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489 if (in->pcm_device_id < 0) {
2490 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2491 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002492 ret = -EINVAL;
2493 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002495
2496 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002498
2499 if (!uc_info) {
2500 ret = -ENOMEM;
2501 goto error_config;
2502 }
2503
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 uc_info->id = in->usecase;
2505 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002506 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002507 uc_info->devices = in->device;
2508 uc_info->in_snd_device = SND_DEVICE_NONE;
2509 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002511 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302512 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2513 adev->perf_lock_opts,
2514 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002515 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516
Haynes Mathew George16081042017-05-31 17:16:49 -07002517 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302518 ret = audio_extn_cin_start_input_stream(in);
2519 if (ret)
2520 goto error_open;
2521 else
2522 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002523 }
2524
Haynes Mathew George16081042017-05-31 17:16:49 -07002525 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002526 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002527 ALOGE("%s: pcm stream not ready", __func__);
2528 goto error_open;
2529 }
2530 ret = pcm_start(in->pcm);
2531 if (ret < 0) {
2532 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2533 goto error_open;
2534 }
2535 } else {
2536 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2537 unsigned int pcm_open_retry_count = 0;
2538
2539 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2540 flags |= PCM_MMAP | PCM_NOIRQ;
2541 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2542 } else if (in->realtime) {
2543 flags |= PCM_MMAP | PCM_NOIRQ;
2544 }
2545
Garmond Leunge2433c32017-09-28 21:51:22 -07002546 if (audio_extn_ffv_get_stream() == in) {
2547 ALOGD("%s: ffv stream, update pcm config", __func__);
2548 audio_extn_ffv_update_pcm_config(&config);
2549 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002550 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2551 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2552
2553 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002554 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002555 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002556 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002557 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002558 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2559 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2560 if (in->pcm != NULL) {
2561 pcm_close(in->pcm);
2562 in->pcm = NULL;
2563 }
2564 if (pcm_open_retry_count-- == 0) {
2565 ret = -EIO;
2566 goto error_open;
2567 }
2568 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2569 continue;
2570 }
2571 break;
2572 }
2573
2574 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002575 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002576 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002577 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002578 if (ret < 0) {
2579 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2580 pcm_close(in->pcm);
2581 in->pcm = NULL;
2582 goto error_open;
2583 }
2584 register_in_stream(in);
2585 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002586 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002587 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002588 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002589 if (ret < 0) {
2590 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002591 pcm_close(in->pcm);
2592 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002593 goto error_open;
2594 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002595 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002596 }
2597
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002598 check_and_enable_effect(adev);
2599
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302600done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302601 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002602 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002603
Eric Laurentc8400632013-02-14 19:04:54 -08002604 return ret;
2605
2606error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302607 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002609error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302610 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302611 /*
2612 * sleep 50ms to allow sufficient time for kernel
2613 * drivers to recover incases like SSR.
2614 */
2615 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002616 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002617
2618 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619}
2620
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002621void lock_input_stream(struct stream_in *in)
2622{
2623 pthread_mutex_lock(&in->pre_lock);
2624 pthread_mutex_lock(&in->lock);
2625 pthread_mutex_unlock(&in->pre_lock);
2626}
2627
2628void lock_output_stream(struct stream_out *out)
2629{
2630 pthread_mutex_lock(&out->pre_lock);
2631 pthread_mutex_lock(&out->lock);
2632 pthread_mutex_unlock(&out->pre_lock);
2633}
2634
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002635/* must be called with out->lock locked */
2636static int send_offload_cmd_l(struct stream_out* out, int command)
2637{
2638 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2639
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002640 if (!cmd) {
2641 ALOGE("failed to allocate mem for command 0x%x", command);
2642 return -ENOMEM;
2643 }
2644
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002645 ALOGVV("%s %d", __func__, command);
2646
2647 cmd->cmd = command;
2648 list_add_tail(&out->offload_cmd_list, &cmd->node);
2649 pthread_cond_signal(&out->offload_cond);
2650 return 0;
2651}
2652
2653/* must be called iwth out->lock locked */
2654static void stop_compressed_output_l(struct stream_out *out)
2655{
2656 out->offload_state = OFFLOAD_STATE_IDLE;
2657 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002658 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002659 if (out->compr != NULL) {
2660 compress_stop(out->compr);
2661 while (out->offload_thread_blocked) {
2662 pthread_cond_wait(&out->cond, &out->lock);
2663 }
2664 }
2665}
2666
Varun Balaraje49253e2017-07-06 19:48:56 +05302667bool is_interactive_usecase(audio_usecase_t uc_id)
2668{
2669 unsigned int i;
2670 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2671 if (uc_id == interactive_usecases[i])
2672 return true;
2673 }
2674 return false;
2675}
2676
2677static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2678{
2679 audio_usecase_t ret_uc = USECASE_INVALID;
2680 unsigned int intract_uc_index;
2681 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2682
2683 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2684 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2685 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2686 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2687 ret_uc = interactive_usecases[intract_uc_index];
2688 break;
2689 }
2690 }
2691
2692 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2693 return ret_uc;
2694}
2695
2696static void free_interactive_usecase(struct audio_device *adev,
2697 audio_usecase_t uc_id)
2698{
2699 unsigned int interact_uc_index;
2700 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2701
2702 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2703 if (interactive_usecases[interact_uc_index] == uc_id) {
2704 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2705 break;
2706 }
2707 }
2708 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2709}
2710
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002711bool is_offload_usecase(audio_usecase_t uc_id)
2712{
2713 unsigned int i;
2714 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2715 if (uc_id == offload_usecases[i])
2716 return true;
2717 }
2718 return false;
2719}
2720
Dhananjay Kumarac341582017-02-23 23:42:25 +05302721static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002722{
vivek mehta446c3962015-09-14 10:57:35 -07002723 audio_usecase_t ret_uc = USECASE_INVALID;
2724 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002725 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002726 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302727 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002728 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2729 else
2730 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002731
vivek mehta446c3962015-09-14 10:57:35 -07002732 pthread_mutex_lock(&adev->lock);
2733 if (get_usecase_from_list(adev, ret_uc) != NULL)
2734 ret_uc = USECASE_INVALID;
2735 pthread_mutex_unlock(&adev->lock);
2736
2737 return ret_uc;
2738 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002739
2740 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002741 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2742 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2743 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2744 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002745 break;
2746 }
2747 }
vivek mehta446c3962015-09-14 10:57:35 -07002748
2749 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2750 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002751}
2752
2753static void free_offload_usecase(struct audio_device *adev,
2754 audio_usecase_t uc_id)
2755{
vivek mehta446c3962015-09-14 10:57:35 -07002756 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002757 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002758
2759 if (!adev->multi_offload_enable)
2760 return;
2761
2762 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2763 if (offload_usecases[offload_uc_index] == uc_id) {
2764 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002765 break;
2766 }
2767 }
2768 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2769}
2770
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002771static void *offload_thread_loop(void *context)
2772{
2773 struct stream_out *out = (struct stream_out *) context;
2774 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002775 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002776
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002777 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2778 set_sched_policy(0, SP_FOREGROUND);
2779 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2780
2781 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002782 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002783 for (;;) {
2784 struct offload_cmd *cmd = NULL;
2785 stream_callback_event_t event;
2786 bool send_callback = false;
2787
2788 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2789 __func__, list_empty(&out->offload_cmd_list),
2790 out->offload_state);
2791 if (list_empty(&out->offload_cmd_list)) {
2792 ALOGV("%s SLEEPING", __func__);
2793 pthread_cond_wait(&out->offload_cond, &out->lock);
2794 ALOGV("%s RUNNING", __func__);
2795 continue;
2796 }
2797
2798 item = list_head(&out->offload_cmd_list);
2799 cmd = node_to_item(item, struct offload_cmd, node);
2800 list_remove(item);
2801
2802 ALOGVV("%s STATE %d CMD %d out->compr %p",
2803 __func__, out->offload_state, cmd->cmd, out->compr);
2804
2805 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2806 free(cmd);
2807 break;
2808 }
2809
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002810 // allow OFFLOAD_CMD_ERROR reporting during standby
2811 // this is needed to handle failures during compress_open
2812 // Note however that on a pause timeout, the stream is closed
2813 // and no offload usecase will be active. Therefore this
2814 // special case is needed for compress_open failures alone
2815 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2816 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002817 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002818 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002819 pthread_cond_signal(&out->cond);
2820 continue;
2821 }
2822 out->offload_thread_blocked = true;
2823 pthread_mutex_unlock(&out->lock);
2824 send_callback = false;
2825 switch(cmd->cmd) {
2826 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002827 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002828 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002829 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002830 send_callback = true;
2831 event = STREAM_CBK_EVENT_WRITE_READY;
2832 break;
2833 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002834 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302835 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002836 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302837 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002838 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302839 if (ret < 0)
2840 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302841 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302842 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002843 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002844 else
2845 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002846 if (-ENETRESET != ret && !(-EINTR == ret &&
2847 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302848 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302849 pthread_mutex_lock(&out->lock);
2850 out->send_new_metadata = 1;
2851 out->send_next_track_params = true;
2852 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302853 event = STREAM_CBK_EVENT_DRAIN_READY;
2854 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2855 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302856 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002857 break;
2858 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002859 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002860 ret = compress_drain(out->compr);
2861 ALOGD("copl(%p):out of compress_drain", out);
2862 // EINTR check avoids drain interruption due to SSR
2863 if (-ENETRESET != ret && !(-EINTR == ret &&
2864 CARD_STATUS_OFFLINE == out->card_status)) {
2865 send_callback = true;
2866 event = STREAM_CBK_EVENT_DRAIN_READY;
2867 } else
2868 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002869 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302870 case OFFLOAD_CMD_ERROR:
2871 ALOGD("copl(%p): sending error callback to AF", out);
2872 send_callback = true;
2873 event = STREAM_CBK_EVENT_ERROR;
2874 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002875 default:
2876 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2877 break;
2878 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002879 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002880 out->offload_thread_blocked = false;
2881 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002882 if (send_callback && out->client_callback) {
2883 ALOGVV("%s: sending client_callback event %d", __func__, event);
2884 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002885 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002886 free(cmd);
2887 }
2888
2889 pthread_cond_signal(&out->cond);
2890 while (!list_empty(&out->offload_cmd_list)) {
2891 item = list_head(&out->offload_cmd_list);
2892 list_remove(item);
2893 free(node_to_item(item, struct offload_cmd, node));
2894 }
2895 pthread_mutex_unlock(&out->lock);
2896
2897 return NULL;
2898}
2899
2900static int create_offload_callback_thread(struct stream_out *out)
2901{
2902 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2903 list_init(&out->offload_cmd_list);
2904 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2905 offload_thread_loop, out);
2906 return 0;
2907}
2908
2909static int destroy_offload_callback_thread(struct stream_out *out)
2910{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002911 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002912 stop_compressed_output_l(out);
2913 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2914
2915 pthread_mutex_unlock(&out->lock);
2916 pthread_join(out->offload_thread, (void **) NULL);
2917 pthread_cond_destroy(&out->offload_cond);
2918
2919 return 0;
2920}
2921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922static int stop_output_stream(struct stream_out *out)
2923{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302924 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002925 struct audio_usecase *uc_info;
2926 struct audio_device *adev = out->dev;
2927
Eric Laurent994a6932013-07-17 11:51:42 -07002928 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002929 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002930 uc_info = get_usecase_from_list(adev, out->usecase);
2931 if (uc_info == NULL) {
2932 ALOGE("%s: Could not find the usecase (%d) in the list",
2933 __func__, out->usecase);
2934 return -EINVAL;
2935 }
2936
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002937 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302938 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002939 if (adev->visualizer_stop_output != NULL)
2940 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002941
2942 audio_extn_dts_remove_state_notifier_node(out->usecase);
2943
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002944 if (adev->offload_effects_stop_output != NULL)
2945 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2946 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002947
Arun Mirpurief53ce52018-09-11 18:00:09 -07002948 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2949 voice_set_device_mute_flag(adev, false);
2950
Eric Laurent150dbfe2013-02-27 14:31:02 -08002951 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002952 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002953
2954 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002955 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002956
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002957 if (is_offload_usecase(out->usecase)) {
2958 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2959 adev->dsp_bit_width_enforce_mode,
2960 false);
2961 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07002962 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2963 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
2964 false);
2965
2966 if (ret != 0)
2967 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
2968 /* default service interval was successfully updated,
2969 reopen USB backend with new service interval */
2970 ret = 0;
2971 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002972
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002973 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302974 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002975 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302976 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002977 ALOGV("Disable passthrough , reset mixer to pcm");
2978 /* NO_PASSTHROUGH */
2979 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002980 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002981 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2982 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002983
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302984 /* Must be called after removing the usecase from list */
2985 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05302986 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302987
Manish Dewangan21a850a2017-08-14 12:03:55 +05302988 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002989 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2990 if (ret < 0)
2991 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2992 }
2993
Garmond Leung5fd0b552018-04-17 11:56:12 -07002994 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002995 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996 return ret;
2997}
2998
2999int start_output_stream(struct stream_out *out)
3000{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002 struct audio_usecase *uc_info;
3003 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003004 char mixer_ctl_name[128];
3005 struct mixer_ctl *ctl = NULL;
3006 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303007 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008
Haynes Mathew George380745d2017-10-04 15:27:45 -07003009 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003010 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3011 ret = -EINVAL;
3012 goto error_config;
3013 }
3014
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303015 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
3016 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
3017 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303018
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303019 if (CARD_STATUS_OFFLINE == out->card_status ||
3020 CARD_STATUS_OFFLINE == adev->card_status) {
3021 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303022 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303023 goto error_config;
3024 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303025
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303026 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
3027 if (!audio_extn_a2dp_is_ready()) {
3028 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303029 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303030 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303031 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3032 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3033 ret = -EAGAIN;
3034 goto error_config;
3035 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303036 }
3037 }
3038 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303039 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3040 if (!adev->bt_sco_on) {
3041 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3042 //combo usecase just by pass a2dp
3043 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3044 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3045 } else {
3046 ALOGE("%s: SCO profile is not ready, return error", __func__);
3047 ret = -EAGAIN;
3048 goto error_config;
3049 }
3050 }
3051 }
3052
Eric Laurentb23d5282013-05-14 15:27:20 -07003053 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003054 if (out->pcm_device_id < 0) {
3055 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3056 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003057 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003058 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059 }
3060
3061 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003062
3063 if (!uc_info) {
3064 ret = -ENOMEM;
3065 goto error_config;
3066 }
3067
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068 uc_info->id = out->usecase;
3069 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003070 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003071 uc_info->devices = out->devices;
3072 uc_info->in_snd_device = SND_DEVICE_NONE;
3073 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003074
3075 /* This must be called before adding this usecase to the list */
3076 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3077 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3078 /* USB backend is not reopened immediately.
3079 This is eventually done as part of select_devices */
3080 }
3081
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003082 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303084 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3085 adev->perf_lock_opts,
3086 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303087
3088 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303089 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303090 if (audio_extn_passthru_is_enabled() &&
3091 audio_extn_passthru_is_passthrough_stream(out)) {
3092 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303093 }
3094 }
3095
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303096 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3097 (!audio_extn_a2dp_is_ready())) {
3098 if (!a2dp_combo) {
3099 check_a2dp_restore_l(adev, out, false);
3100 } else {
3101 audio_devices_t dev = out->devices;
3102 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3103 select_devices(adev, out->usecase);
3104 out->devices = dev;
3105 }
3106 } else {
3107 select_devices(adev, out->usecase);
3108 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003109
Arun Mirpurief53ce52018-09-11 18:00:09 -07003110 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3111 voice_set_device_mute_flag(adev, true);
3112
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003113 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3114 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003115
3116 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuriebe78a72018-10-04 18:23:46 -07003117 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003118 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3119 ALOGE("%s: pcm stream not ready", __func__);
3120 goto error_open;
3121 }
3122 ret = pcm_start(out->pcm);
3123 if (ret < 0) {
3124 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3125 goto error_open;
3126 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07003127 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003128 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003129 unsigned int flags = PCM_OUT;
3130 unsigned int pcm_open_retry_count = 0;
3131 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3132 flags |= PCM_MMAP | PCM_NOIRQ;
3133 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003134 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003135 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003136 } else
3137 flags |= PCM_MONOTONIC;
3138
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003139 if ((adev->vr_audio_mode_enabled) &&
3140 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3141 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3142 "PCM_Dev %d Topology", out->pcm_device_id);
3143 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3144 if (!ctl) {
3145 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3146 __func__, mixer_ctl_name);
3147 } else {
3148 //if success use ULLPP
3149 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3150 __func__, mixer_ctl_name, out->pcm_device_id);
3151 //There is a still a possibility that some sessions
3152 // that request for FAST|RAW when 3D audio is active
3153 //can go through ULLPP. Ideally we expects apps to
3154 //listen to audio focus and stop concurrent playback
3155 //Also, we will look for mode flag (voice_in_communication)
3156 //before enabling the realtime flag.
3157 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3158 }
3159 }
3160
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003161 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003162 ATRACE_BEGIN("pcm_open");
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003163 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3164 flags, &out->config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003165 ATRACE_END();
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003166 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3167 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3168 if (out->pcm != NULL) {
3169 pcm_close(out->pcm);
3170 out->pcm = NULL;
3171 }
3172 if (pcm_open_retry_count-- == 0) {
3173 ret = -EIO;
3174 goto error_open;
3175 }
3176 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3177 continue;
3178 }
3179 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003180 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003181
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003182 ALOGV("%s: pcm_prepare", __func__);
3183 if (pcm_is_ready(out->pcm)) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003184 ATRACE_BEGIN("pcm_prepare");
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003185 ret = pcm_prepare(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003186 ATRACE_END();
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003187 if (ret < 0) {
3188 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3189 pcm_close(out->pcm);
3190 out->pcm = NULL;
3191 goto error_open;
3192 }
3193 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05303194 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303195 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08003196 // apply volume for voip playback after path is set up
3197 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3198 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003199 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003200 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303201 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003202 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3203 adev->dsp_bit_width_enforce_mode,
3204 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003205 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003206 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003207 out->compr = compress_open(adev->snd_card,
3208 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003209 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003210 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003211 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003212 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003213 compress_close(out->compr);
3214 out->compr = NULL;
3215 ret = -EIO;
3216 goto error_open;
3217 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303218 /* compress_open sends params of the track, so reset the flag here */
3219 out->is_compr_metadata_avail = false;
3220
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003221 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003222 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003223
Fred Oh3f43e742015-03-04 18:42:34 -08003224 /* Since small bufs uses blocking writes, a write will be blocked
3225 for the default max poll time (20s) in the event of an SSR.
3226 Reduce the poll time to observe and deal with SSR faster.
3227 */
Ashish Jain5106d362016-05-11 19:23:33 +05303228 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003229 compress_set_max_poll_wait(out->compr, 1000);
3230 }
3231
Manish Dewangan69426c82017-01-30 17:35:36 +05303232 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303233 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303234
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003235 audio_extn_dts_create_state_notifier_node(out->usecase);
3236 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3237 popcount(out->channel_mask),
3238 out->playback_started);
3239
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003240#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303241 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003242 audio_extn_dolby_send_ddp_endp_params(adev);
3243#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303244 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3245 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003246 if (adev->visualizer_start_output != NULL)
3247 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3248 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303249 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003250 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003251 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003253
3254 if (ret == 0) {
3255 register_out_stream(out);
3256 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003257 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3258 ALOGE("%s: pcm stream not ready", __func__);
3259 goto error_open;
3260 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003261 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003262 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003263 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003264 if (ret < 0)
3265 goto error_open;
3266 }
3267 }
3268
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303269 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003270 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003271
Manish Dewangan21a850a2017-08-14 12:03:55 +05303272 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003273 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003274 if (ret < 0)
3275 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3276 }
3277
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003278 // consider a scenario where on pause lower layers are tear down.
3279 // so on resume, swap mixer control need to be sent only when
3280 // backend is active, hence rather than sending from enable device
3281 // sending it from start of streamtream
3282
3283 platform_set_swap_channels(adev, true);
3284
Haynes Mathew George380745d2017-10-04 15:27:45 -07003285 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003286 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003287error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303288 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003289 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003290error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303291 /*
3292 * sleep 50ms to allow sufficient time for kernel
3293 * drivers to recover incases like SSR.
3294 */
3295 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003296 ATRACE_END();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003297 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298}
3299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300static int check_input_parameters(uint32_t sample_rate,
3301 audio_format_t format,
3302 int channel_count)
3303{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003304 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003305
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303306 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3307 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3308 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003309 !voice_extn_compress_voip_is_format_supported(format) &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003310 !audio_extn_compr_cap_format_supported(format))
3311 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003312
3313 switch (channel_count) {
3314 case 1:
3315 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303316 case 3:
3317 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003318 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003319 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003320 break;
3321 default:
3322 ret = -EINVAL;
3323 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324
3325 switch (sample_rate) {
3326 case 8000:
3327 case 11025:
3328 case 12000:
3329 case 16000:
3330 case 22050:
3331 case 24000:
3332 case 32000:
3333 case 44100:
3334 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003335 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303336 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003337 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303338 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339 break;
3340 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003341 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003342 }
3343
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003344 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345}
3346
Naresh Tanniru04f71882018-06-26 17:46:22 +05303347
3348/** Add a value in a list if not already present.
3349 * @return true if value was successfully inserted or already present,
3350 * false if the list is full and does not contain the value.
3351 */
3352static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3353 for (size_t i = 0; i < list_length; i++) {
3354 if (list[i] == value) return true; // value is already present
3355 if (list[i] == 0) { // no values in this slot
3356 list[i] = value;
3357 return true; // value inserted
3358 }
3359 }
3360 return false; // could not insert value
3361}
3362
3363/** Add channel_mask in supported_channel_masks if not already present.
3364 * @return true if channel_mask was successfully inserted or already present,
3365 * false if supported_channel_masks is full and does not contain channel_mask.
3366 */
3367static void register_channel_mask(audio_channel_mask_t channel_mask,
3368 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3369 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3370 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3371}
3372
3373/** Add format in supported_formats if not already present.
3374 * @return true if format was successfully inserted or already present,
3375 * false if supported_formats is full and does not contain format.
3376 */
3377static void register_format(audio_format_t format,
3378 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3379 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3380 "%s: stream can not declare supporting its format %x", __func__, format);
3381}
3382/** Add sample_rate in supported_sample_rates if not already present.
3383 * @return true if sample_rate was successfully inserted or already present,
3384 * false if supported_sample_rates is full and does not contain sample_rate.
3385 */
3386static void register_sample_rate(uint32_t sample_rate,
3387 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3388 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3389 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3390}
3391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392static size_t get_input_buffer_size(uint32_t sample_rate,
3393 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003394 int channel_count,
3395 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396{
3397 size_t size = 0;
3398
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003399 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3400 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003402 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003403 if (is_low_latency)
3404 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303405
3406 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003407
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003408 /* make sure the size is multiple of 32 bytes
3409 * At 48 kHz mono 16-bit PCM:
3410 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3411 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
3412 */
3413 size += 0x1f;
3414 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003415
3416 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417}
3418
Ashish Jain058165c2016-09-28 23:18:48 +05303419static size_t get_output_period_size(uint32_t sample_rate,
3420 audio_format_t format,
3421 int channel_count,
3422 int duration /*in millisecs*/)
3423{
3424 size_t size = 0;
3425 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3426
3427 if ((duration == 0) || (sample_rate == 0) ||
3428 (bytes_per_sample == 0) || (channel_count == 0)) {
3429 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3430 bytes_per_sample, channel_count);
3431 return -EINVAL;
3432 }
3433
3434 size = (sample_rate *
3435 duration *
3436 bytes_per_sample *
3437 channel_count) / 1000;
3438 /*
3439 * To have same PCM samples for all channels, the buffer size requires to
3440 * be multiple of (number of channels * bytes per sample)
3441 * For writes to succeed, the buffer must be written at address which is multiple of 32
3442 */
3443 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3444
3445 return (size/(channel_count * bytes_per_sample));
3446}
3447
Zhou Song48453a02018-01-10 17:50:59 +08003448static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303449{
3450 uint64_t actual_frames_rendered = 0;
3451 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3452
3453 /* This adjustment accounts for buffering after app processor.
3454 * It is based on estimated DSP latency per use case, rather than exact.
3455 */
3456 int64_t platform_latency = platform_render_latency(out->usecase) *
3457 out->sample_rate / 1000000LL;
3458
Zhou Song48453a02018-01-10 17:50:59 +08003459 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303460 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3461 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3462 * hence only estimate.
3463 */
3464 int64_t signed_frames = out->written - kernel_buffer_size;
3465
3466 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3467
Zhou Song48453a02018-01-10 17:50:59 +08003468 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303469 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003470 if (timestamp != NULL )
3471 *timestamp = out->writeAt;
3472 } else if (timestamp != NULL) {
3473 clock_gettime(CLOCK_MONOTONIC, timestamp);
3474 }
3475 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303476
3477 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3478 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3479 (long long int)out->written, (int)kernel_buffer_size,
3480 audio_bytes_per_sample(out->compr_config.codec->format),
3481 popcount(out->channel_mask));
3482
3483 return actual_frames_rendered;
3484}
3485
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3487{
3488 struct stream_out *out = (struct stream_out *)stream;
3489
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003490 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491}
3492
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003493static int out_set_sample_rate(struct audio_stream *stream __unused,
3494 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495{
3496 return -ENOSYS;
3497}
3498
3499static size_t out_get_buffer_size(const struct audio_stream *stream)
3500{
3501 struct stream_out *out = (struct stream_out *)stream;
3502
Varun Balaraje49253e2017-07-06 19:48:56 +05303503 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303504 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303505 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303506 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3507 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3508 else
3509 return out->compr_config.fragment_size;
3510 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003511 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003512 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3513 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 +05303514 else if (is_offload_usecase(out->usecase) &&
3515 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303516 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003517
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003518 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003519 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520}
3521
3522static uint32_t out_get_channels(const struct audio_stream *stream)
3523{
3524 struct stream_out *out = (struct stream_out *)stream;
3525
3526 return out->channel_mask;
3527}
3528
3529static audio_format_t out_get_format(const struct audio_stream *stream)
3530{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003531 struct stream_out *out = (struct stream_out *)stream;
3532
3533 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534}
3535
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003536static int out_set_format(struct audio_stream *stream __unused,
3537 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538{
3539 return -ENOSYS;
3540}
3541
3542static int out_standby(struct audio_stream *stream)
3543{
3544 struct stream_out *out = (struct stream_out *)stream;
3545 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003546 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003547
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303548 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3549 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003551 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003552 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003553 if (adev->adm_deregister_stream)
3554 adev->adm_deregister_stream(adev->adm_data, out->handle);
3555
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003556 if (is_offload_usecase(out->usecase))
3557 stop_compressed_output_l(out);
3558
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003559 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003561 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3562 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303563 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003564 pthread_mutex_unlock(&adev->lock);
3565 pthread_mutex_unlock(&out->lock);
3566 ALOGD("VOIP output entered standby");
3567 return 0;
3568 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003569 if (out->pcm) {
3570 pcm_close(out->pcm);
3571 out->pcm = NULL;
3572 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003573 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3574 do_stop = out->playback_started;
3575 out->playback_started = false;
3576 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003577 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003578 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303579 out->send_next_track_params = false;
3580 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003581 out->gapless_mdata.encoder_delay = 0;
3582 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003583 if (out->compr != NULL) {
3584 compress_close(out->compr);
3585 out->compr = NULL;
3586 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003587 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003588 if (do_stop) {
3589 stop_output_stream(out);
3590 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003591 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003592 }
3593 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303594 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003595 return 0;
3596}
3597
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303598static int out_on_error(struct audio_stream *stream)
3599{
3600 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003601 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303602
3603 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003604 // always send CMD_ERROR for offload streams, this
3605 // is needed e.g. when SSR happens within compress_open
3606 // since the stream is active, offload_callback_thread is also active.
3607 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3608 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003609 }
3610 pthread_mutex_unlock(&out->lock);
3611
3612 status = out_standby(&out->stream.common);
3613
3614 lock_output_stream(out);
3615 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003616 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303617 }
3618 pthread_mutex_unlock(&out->lock);
3619
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003620 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303621}
3622
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303623/*
3624 *standby implementation without locks, assumes that the callee already
3625 *has taken adev and out lock.
3626 */
3627int out_standby_l(struct audio_stream *stream)
3628{
3629 struct stream_out *out = (struct stream_out *)stream;
3630 struct audio_device *adev = out->dev;
3631
3632 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3633 stream, out->usecase, use_case_table[out->usecase]);
3634
3635 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003636 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303637 if (adev->adm_deregister_stream)
3638 adev->adm_deregister_stream(adev->adm_data, out->handle);
3639
3640 if (is_offload_usecase(out->usecase))
3641 stop_compressed_output_l(out);
3642
3643 out->standby = true;
3644 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3645 voice_extn_compress_voip_close_output_stream(stream);
3646 out->started = 0;
3647 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003648 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303649 return 0;
3650 } else if (!is_offload_usecase(out->usecase)) {
3651 if (out->pcm) {
3652 pcm_close(out->pcm);
3653 out->pcm = NULL;
3654 }
3655 } else {
3656 ALOGD("copl(%p):standby", out);
3657 out->send_next_track_params = false;
3658 out->is_compr_metadata_avail = false;
3659 out->gapless_mdata.encoder_delay = 0;
3660 out->gapless_mdata.encoder_padding = 0;
3661 if (out->compr != NULL) {
3662 compress_close(out->compr);
3663 out->compr = NULL;
3664 }
3665 }
3666 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003667 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303668 }
3669 ALOGD("%s: exit", __func__);
3670 return 0;
3671}
3672
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003673static int out_dump(const struct audio_stream *stream __unused,
3674 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675{
3676 return 0;
3677}
3678
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003679static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3680{
3681 int ret = 0;
3682 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003683
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003684 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003685 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003686 return -EINVAL;
3687 }
3688
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303689 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003690
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003691 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3692 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303693 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003694 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003695 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3696 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303697 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003698 }
3699
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003700 ALOGV("%s new encoder delay %u and padding %u", __func__,
3701 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3702
3703 return 0;
3704}
3705
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003706static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3707{
3708 return out == adev->primary_output || out == adev->voice_tx_output;
3709}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003710
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303711// note: this call is safe only if the stream_cb is
3712// removed first in close_output_stream (as is done now).
3713static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3714{
3715 if (!stream || !parms)
3716 return;
3717
3718 struct stream_out *out = (struct stream_out *)stream;
3719 struct audio_device *adev = out->dev;
3720
3721 card_status_t status;
3722 int card;
3723 if (parse_snd_card_status(parms, &card, &status) < 0)
3724 return;
3725
3726 pthread_mutex_lock(&adev->lock);
3727 bool valid_cb = (card == adev->snd_card);
3728 pthread_mutex_unlock(&adev->lock);
3729
3730 if (!valid_cb)
3731 return;
3732
3733 lock_output_stream(out);
3734 if (out->card_status != status)
3735 out->card_status = status;
3736 pthread_mutex_unlock(&out->lock);
3737
3738 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3739 use_case_table[out->usecase],
3740 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3741
3742 if (status == CARD_STATUS_OFFLINE)
3743 out_on_error(stream);
3744
3745 return;
3746}
3747
Kevin Rocardfce19002017-08-07 19:21:36 -07003748static int get_alive_usb_card(struct str_parms* parms) {
3749 int card;
3750 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
3751 !audio_extn_usb_alive(card)) {
3752 return card;
3753 }
3754 return -ENODEV;
3755}
3756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3758{
3759 struct stream_out *out = (struct stream_out *)stream;
3760 struct audio_device *adev = out->dev;
3761 struct str_parms *parms;
3762 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003763 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303764 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003765 bool reconfig = false;
3766 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767
sangwoobc677242013-08-08 16:53:43 +09003768 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003769 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303771 if (!parms)
3772 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003773 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3774 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003775 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003776 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003777 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003779 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003780 * When HDMI cable is unplugged the music playback is paused and
3781 * the policy manager sends routing=0. But the audioflinger continues
3782 * to write data until standby time (3sec). As the HDMI core is
3783 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003784 * Avoid this by routing audio to speaker until standby.
3785 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003786 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3787 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303788 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003789 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3790 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003791 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303792 /*
3793 * When A2DP is disconnected the
3794 * music playback is paused and the policy manager sends routing=0
3795 * But the audioflingercontinues to write data until standby time
3796 * (3sec). As BT is turned off, the write gets blocked.
3797 * Avoid this by routing audio to speaker until standby.
3798 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003799 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07003800 (val == AUDIO_DEVICE_NONE) &&
3801 !audio_extn_a2dp_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303802 val = AUDIO_DEVICE_OUT_SPEAKER;
3803 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05303804 /*
3805 * When USB headset is disconnected the music platback paused
3806 * and the policy manager send routing=0. But if the USB is connected
3807 * back before the standby time, AFE is not closed and opened
3808 * when USB is connected back. So routing to speker will guarantee
3809 * AFE reconfiguration and AFE will be opend once USB is connected again
3810 */
3811 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
3812 (val == AUDIO_DEVICE_NONE) &&
3813 !audio_extn_usb_connected(parms)) {
3814 val = AUDIO_DEVICE_OUT_SPEAKER;
3815 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303816 /* To avoid a2dp to sco overlapping / BT device improper state
3817 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303818 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303819 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3820 if (!audio_extn_a2dp_is_ready()) {
3821 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3822 //combo usecase just by pass a2dp
3823 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303824 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303825 } else {
3826 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3827 /* update device to a2dp and don't route as BT returned error
3828 * However it is still possible a2dp routing called because
3829 * of current active device disconnection (like wired headset)
3830 */
3831 out->devices = val;
3832 pthread_mutex_unlock(&out->lock);
3833 pthread_mutex_unlock(&adev->lock);
3834 goto error;
3835 }
3836 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303837 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003838
3839 audio_devices_t new_dev = val;
3840
3841 // Workaround: If routing to an non existing usb device, fail gracefully
3842 // The routing request will otherwise block during 10 second
3843 int card;
3844 if (audio_is_usb_out_device(new_dev) &&
3845 (card = get_alive_usb_card(parms)) >= 0) {
3846
3847 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
3848 pthread_mutex_unlock(&adev->lock);
3849 pthread_mutex_unlock(&out->lock);
3850 ret = -ENOSYS;
3851 goto routing_fail;
3852 }
3853
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003854 /*
3855 * select_devices() call below switches all the usecases on the same
3856 * backend to the new device. Refer to check_usecases_codec_backend() in
3857 * the select_devices(). But how do we undo this?
3858 *
3859 * For example, music playback is active on headset (deep-buffer usecase)
3860 * and if we go to ringtones and select a ringtone, low-latency usecase
3861 * will be started on headset+speaker. As we can't enable headset+speaker
3862 * and headset devices at the same time, select_devices() switches the music
3863 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3864 * So when the ringtone playback is completed, how do we undo the same?
3865 *
3866 * We are relying on the out_set_parameters() call on deep-buffer output,
3867 * once the ringtone playback is ended.
3868 * NOTE: We should not check if the current devices are same as new devices.
3869 * Because select_devices() must be called to switch back the music
3870 * playback to headset.
3871 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003872 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003873 audio_devices_t new_dev = val;
3874 bool same_dev = out->devices == new_dev;
3875 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003876
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003877 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08003878 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003879 if (adev->mode == AUDIO_MODE_IN_CALL) {
3880 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003881 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3882 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
3883 audio_extn_usb_set_service_interval(true /*playback*/,
3884 service_interval,
3885 &reconfig);
3886 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
3887 }
3888 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003889 }
3890 } else {
3891 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003892 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003893 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003894 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003895
3896 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003897 if (!same_dev) {
3898 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303899 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3900 adev->perf_lock_opts,
3901 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003902 if (adev->adm_on_routing_change)
3903 adev->adm_on_routing_change(adev->adm_data,
3904 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003905 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303906 if (!bypass_a2dp) {
3907 select_devices(adev, out->usecase);
3908 } else {
3909 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3910 select_devices(adev, out->usecase);
3911 out->devices = new_dev;
3912 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003913
3914 if (!same_dev) {
3915 // on device switch force swap, lower functions will make sure
3916 // to check if swap is allowed or not.
3917 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05303918 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003919 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303920 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3921 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003922 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303923 pthread_mutex_lock(&out->compr_mute_lock);
3924 out->a2dp_compress_mute = false;
3925 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3926 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08003927 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
3928 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303929 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003930 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003931 }
3932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003933 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003934 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003935 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003936 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003937
3938 if (out == adev->primary_output) {
3939 pthread_mutex_lock(&adev->lock);
3940 audio_extn_set_parameters(adev, parms);
3941 pthread_mutex_unlock(&adev->lock);
3942 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003943 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003944 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003945 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003946
3947 audio_extn_dts_create_state_notifier_node(out->usecase);
3948 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3949 popcount(out->channel_mask),
3950 out->playback_started);
3951
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003952 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003953 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003954
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303955 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3956 if (err >= 0) {
3957 strlcpy(out->profile, value, sizeof(out->profile));
3958 ALOGV("updating stream profile with value '%s'", out->profile);
3959 lock_output_stream(out);
3960 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3961 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07003962 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303963 out->sample_rate, out->bit_width,
3964 out->channel_mask, out->profile,
3965 &out->app_type_cfg);
3966 pthread_mutex_unlock(&out->lock);
3967 }
3968
Alexy Joseph98988832017-01-13 14:56:59 -08003969 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08003970 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
3971 // and vendor.audio.hal.output.suspend.supported is set to true
3972 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08003973 //check suspend parameter only for low latency and if the property
3974 //is enabled
3975 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3976 ALOGI("%s: got suspend_playback %s", __func__, value);
3977 lock_output_stream(out);
3978 if (!strncmp(value, "false", 5)) {
3979 //suspend_playback=false is supposed to set QOS value back to 75%
3980 //the mixer control sent with value Enable will achieve that
3981 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3982 } else if (!strncmp (value, "true", 4)) {
3983 //suspend_playback=true is supposed to remove QOS value
3984 //resetting the mixer control will set the default value
3985 //for the mixer control which is Disable and this removes the QOS vote
3986 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3987 } else {
3988 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3989 " got %s", __func__, value);
3990 ret = -1;
3991 }
3992
3993 if (ret != 0) {
3994 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3995 __func__, out->pm_qos_mixer_path, ret);
3996 }
3997
3998 pthread_mutex_unlock(&out->lock);
3999 }
4000 }
4001 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004002 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304003error:
Eric Laurent994a6932013-07-17 11:51:42 -07004004 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004005 return ret;
4006}
4007
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004008static bool stream_get_parameter_channels(struct str_parms *query,
4009 struct str_parms *reply,
4010 audio_channel_mask_t *supported_channel_masks) {
4011 int ret = -1;
4012 char value[512];
4013 bool first = true;
4014 size_t i, j;
4015
4016 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4017 ret = 0;
4018 value[0] = '\0';
4019 i = 0;
4020 while (supported_channel_masks[i] != 0) {
4021 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4022 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4023 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304024 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004025
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304026 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004027 first = false;
4028 break;
4029 }
4030 }
4031 i++;
4032 }
4033 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4034 }
4035 return ret == 0;
4036}
4037
4038static bool stream_get_parameter_formats(struct str_parms *query,
4039 struct str_parms *reply,
4040 audio_format_t *supported_formats) {
4041 int ret = -1;
4042 char value[256];
4043 size_t i, j;
4044 bool first = true;
4045
4046 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4047 ret = 0;
4048 value[0] = '\0';
4049 i = 0;
4050 while (supported_formats[i] != 0) {
4051 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4052 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4053 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304054 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004055 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304056 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004057 first = false;
4058 break;
4059 }
4060 }
4061 i++;
4062 }
4063 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4064 }
4065 return ret == 0;
4066}
4067
4068static bool stream_get_parameter_rates(struct str_parms *query,
4069 struct str_parms *reply,
4070 uint32_t *supported_sample_rates) {
4071
4072 int i;
4073 char value[256];
4074 int ret = -1;
4075 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4076 ret = 0;
4077 value[0] = '\0';
4078 i=0;
4079 int cursor = 0;
4080 while (supported_sample_rates[i]) {
4081 int avail = sizeof(value) - cursor;
4082 ret = snprintf(value + cursor, avail, "%s%d",
4083 cursor > 0 ? "|" : "",
4084 supported_sample_rates[i]);
4085 if (ret < 0 || ret >= avail) {
4086 // if cursor is at the last element of the array
4087 // overwrite with \0 is duplicate work as
4088 // snprintf already put a \0 in place.
4089 // else
4090 // we had space to write the '|' at value[cursor]
4091 // (which will be overwritten) or no space to fill
4092 // the first element (=> cursor == 0)
4093 value[cursor] = '\0';
4094 break;
4095 }
4096 cursor += ret;
4097 ++i;
4098 }
4099 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4100 value);
4101 }
4102 return ret >= 0;
4103}
4104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004105static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4106{
4107 struct stream_out *out = (struct stream_out *)stream;
4108 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004109 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004110 char value[256];
4111 struct str_parms *reply = str_parms_create();
4112 size_t i, j;
4113 int ret;
4114 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004115
4116 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004117 if (reply) {
4118 str_parms_destroy(reply);
4119 }
4120 if (query) {
4121 str_parms_destroy(query);
4122 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004123 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4124 return NULL;
4125 }
4126
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004127 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004128 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4129 if (ret >= 0) {
4130 value[0] = '\0';
4131 i = 0;
4132 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004133 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4134 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004135 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004136 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004138 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004139 first = false;
4140 break;
4141 }
4142 }
4143 i++;
4144 }
4145 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4146 str = str_parms_to_str(reply);
4147 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004148 voice_extn_out_get_parameters(out, query, reply);
4149 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004150 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004151
Alexy Joseph62142aa2015-11-16 15:10:34 -08004152
4153 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4154 if (ret >= 0) {
4155 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304156 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4157 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004158 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304159 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004160 } else {
4161 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304162 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004163 }
4164 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004165 if (str)
4166 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004167 str = str_parms_to_str(reply);
4168 }
4169
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004170 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4171 if (ret >= 0) {
4172 value[0] = '\0';
4173 i = 0;
4174 first = true;
4175 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004176 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4177 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004178 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004179 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004180 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004181 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004182 first = false;
4183 break;
4184 }
4185 }
4186 i++;
4187 }
4188 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004189 if (str)
4190 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004191 str = str_parms_to_str(reply);
4192 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004193
4194 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4195 if (ret >= 0) {
4196 value[0] = '\0';
4197 i = 0;
4198 first = true;
4199 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004200 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4201 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004202 if (!first) {
4203 strlcat(value, "|", sizeof(value));
4204 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004205 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004206 first = false;
4207 break;
4208 }
4209 }
4210 i++;
4211 }
4212 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4213 if (str)
4214 free(str);
4215 str = str_parms_to_str(reply);
4216 }
4217
Alexy Joseph98988832017-01-13 14:56:59 -08004218 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4219 //only low latency track supports suspend_resume
4220 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004221 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004222 if (str)
4223 free(str);
4224 str = str_parms_to_str(reply);
4225 }
4226
4227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004228 str_parms_destroy(query);
4229 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004230 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004231 return str;
4232}
4233
4234static uint32_t out_get_latency(const struct audio_stream_out *stream)
4235{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004236 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004237 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004238 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004239
Alexy Josephaa54c872014-12-03 02:46:47 -08004240 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304241 lock_output_stream(out);
4242 latency = audio_extn_utils_compress_get_dsp_latency(out);
4243 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004244 } else if ((out->realtime) ||
4245 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004246 // since the buffer won't be filled up faster than realtime,
4247 // return a smaller number
4248 if (out->config.rate)
4249 period_ms = (out->af_period_multiplier * out->config.period_size *
4250 1000) / (out->config.rate);
4251 else
4252 period_ms = 0;
4253 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004254 } else {
4255 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004256 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004257 }
4258
yidongh0515e042017-07-06 15:00:34 +08004259 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004260 latency += audio_extn_a2dp_get_encoder_latency();
4261
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304262 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004263 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004264}
4265
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304266static float AmpToDb(float amplification)
4267{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304268 float db = DSD_VOLUME_MIN_DB;
4269 if (amplification > 0) {
4270 db = 20 * log10(amplification);
4271 if(db < DSD_VOLUME_MIN_DB)
4272 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304273 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304274 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304275}
4276
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004277static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4278 float right)
4279{
4280 struct stream_out *out = (struct stream_out *)stream;
4281 long volume = 0;
4282 char mixer_ctl_name[128] = "";
4283 struct audio_device *adev = out->dev;
4284 struct mixer_ctl *ctl = NULL;
4285 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4286 PCM_PLAYBACK);
4287
4288 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4289 "Playback %d Volume", pcm_device_id);
4290 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4291 if (!ctl) {
4292 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4293 __func__, mixer_ctl_name);
4294 return -EINVAL;
4295 }
4296 if (left != right)
4297 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4298 __func__, left, right);
4299 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4300 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4301 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4302 __func__, mixer_ctl_name, volume);
4303 return -EINVAL;
4304 }
4305 return 0;
4306}
4307
4308
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304309static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4310 float right)
4311{
4312 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304313 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304314 char mixer_ctl_name[128];
4315 struct audio_device *adev = out->dev;
4316 struct mixer_ctl *ctl;
4317 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4318 PCM_PLAYBACK);
4319
4320 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4321 "Compress Playback %d Volume", pcm_device_id);
4322 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4323 if (!ctl) {
4324 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4325 __func__, mixer_ctl_name);
4326 return -EINVAL;
4327 }
4328 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4329 __func__, mixer_ctl_name, left, right);
4330 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4331 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4332 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4333
4334 return 0;
4335}
4336
Zhou Song2b8f28f2017-09-11 10:51:38 +08004337static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4338 float right)
4339{
4340 struct stream_out *out = (struct stream_out *)stream;
4341 char mixer_ctl_name[] = "App Type Gain";
4342 struct audio_device *adev = out->dev;
4343 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304344 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004345
4346 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4347 if (!ctl) {
4348 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4349 __func__, mixer_ctl_name);
4350 return -EINVAL;
4351 }
4352
4353 set_values[0] = 0; //0: Rx Session 1:Tx Session
4354 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304355 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4356 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004357
4358 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4359 return 0;
4360}
4361
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004362static int out_set_volume(struct audio_stream_out *stream, float left,
4363 float right)
4364{
Eric Laurenta9024de2013-04-04 09:19:12 -07004365 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004366 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304367 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004368
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004369 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
4370
Eric Laurenta9024de2013-04-04 09:19:12 -07004371 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4372 /* only take left channel into account: the API is for stereo anyway */
4373 out->muted = (left == 0.0f);
4374 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004375 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304376 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004377 /*
4378 * Set mute or umute on HDMI passthrough stream.
4379 * Only take left channel into account.
4380 * Mute is 0 and unmute 1
4381 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304382 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304383 } else if (out->format == AUDIO_FORMAT_DSD){
4384 char mixer_ctl_name[128] = "DSD Volume";
4385 struct audio_device *adev = out->dev;
4386 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4387
4388 if (!ctl) {
4389 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4390 __func__, mixer_ctl_name);
4391 return -EINVAL;
4392 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304393 volume[0] = (long)(AmpToDb(left));
4394 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304395 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4396 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004397 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304398 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004399 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304400 if (!out->a2dp_compress_mute)
4401 ret = out_set_compr_volume(stream, left, right);
4402 out->volume_l = left;
4403 out->volume_r = right;
4404 pthread_mutex_unlock(&out->compr_mute_lock);
4405 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004406 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004407 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004408 if (!out->standby)
4409 ret = out_set_voip_volume(stream, left, right);
4410 out->volume_l = left;
4411 out->volume_r = right;
4412 return ret;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004413 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4414 ALOGV("%s: MMAP set volume called", __func__);
4415 if (!out->standby)
4416 ret = out_set_mmap_volume(stream, left, right);
4417 out->volume_l = left;
4418 out->volume_r = right;
4419 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004420 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004421
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004422 return -ENOSYS;
4423}
4424
Zhou Songc9672822017-08-16 16:01:39 +08004425static void update_frames_written(struct stream_out *out, size_t bytes)
4426{
4427 size_t bpf = 0;
4428
4429 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4430 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4431 bpf = 1;
4432 else if (!is_offload_usecase(out->usecase))
4433 bpf = audio_bytes_per_sample(out->format) *
4434 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004435
4436 pthread_mutex_lock(&out->position_query_lock);
4437 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004438 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004439 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4440 }
4441 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004442}
4443
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004444static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4445 size_t bytes)
4446{
4447 struct stream_out *out = (struct stream_out *)stream;
4448 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004449 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304450 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004451 const size_t frame_size = audio_stream_out_frame_size(stream);
4452 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004453
Haynes Mathew George380745d2017-10-04 15:27:45 -07004454 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004455 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304456
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304457 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004458
Dhananjay Kumarac341582017-02-23 23:42:25 +05304459 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304460 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304461 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4462 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004463 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304464 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304465 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304466 ALOGD(" %s: sound card is not active/SSR state", __func__);
4467 ret= -EIO;
4468 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304469 }
4470 }
4471
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304472 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304473 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304474 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304475 goto exit;
4476 }
4477
Haynes Mathew George16081042017-05-31 17:16:49 -07004478 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4479 ret = -EINVAL;
4480 goto exit;
4481 }
4482
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304483 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4484 !out->is_iec61937_info_available) {
4485
4486 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4487 out->is_iec61937_info_available = true;
4488 } else if (audio_extn_passthru_is_enabled()) {
4489 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304490 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304491
4492 if((out->format == AUDIO_FORMAT_DTS) ||
4493 (out->format == AUDIO_FORMAT_DTS_HD)) {
4494 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4495 buffer, bytes);
4496 if (ret) {
4497 if (ret != -ENOSYS) {
4498 out->is_iec61937_info_available = false;
4499 ALOGD("iec61937 transmission info not yet updated retry");
4500 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304501 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304502 /* if stream has started and after that there is
4503 * stream config change (iec transmission config)
4504 * then trigger select_device to update backend configuration.
4505 */
4506 out->stream_config_changed = true;
4507 pthread_mutex_lock(&adev->lock);
4508 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304509 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4510 ret = -EINVAL;
4511 goto exit;
4512 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304513 pthread_mutex_unlock(&adev->lock);
4514 out->stream_config_changed = false;
4515 out->is_iec61937_info_available = true;
4516 }
4517 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304518
Garmond Leung317cbf12017-09-13 16:20:50 -07004519 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304520 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4521 (out->is_iec61937_info_available == true)) {
4522 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4523 ret = -EINVAL;
4524 goto exit;
4525 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304526 }
4527 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304528
4529 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4530 (audio_extn_a2dp_is_suspended())) {
4531 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4532 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304533 ret = -EIO;
4534 goto exit;
4535 }
4536 }
4537 }
4538
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004539 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004540 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004541 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004542 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4543 ret = voice_extn_compress_voip_start_output_stream(out);
4544 else
4545 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004546 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004547 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004548 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004549 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004550 goto exit;
4551 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304552 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004553 if (last_known_cal_step != -1) {
4554 ALOGD("%s: retry previous failed cal level set", __func__);
4555 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304556 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004557 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304558
4559 if ((out->is_iec61937_info_available == true) &&
4560 (audio_extn_passthru_is_passthrough_stream(out))&&
4561 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4562 ret = -EINVAL;
4563 goto exit;
4564 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004565 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004566
Ashish Jain81eb2a82015-05-13 10:52:34 +05304567 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004568 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304569 adev->is_channel_status_set = true;
4570 }
4571
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004572 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004573 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004574 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004575 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004576 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4577 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304578 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4579 ALOGD("copl(%p):send next track params in gapless", out);
4580 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4581 out->send_next_track_params = false;
4582 out->is_compr_metadata_avail = false;
4583 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004584 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304585 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304586 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004587
Ashish Jain83a6cc22016-06-28 14:34:17 +05304588 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304589 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304590 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304591 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004592 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304593 return -EINVAL;
4594 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304595 audio_format_t dst_format = out->hal_op_format;
4596 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304597
4598 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4599 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4600
Ashish Jain83a6cc22016-06-28 14:34:17 +05304601 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304602 dst_format,
4603 buffer,
4604 src_format,
4605 frames);
4606
Ashish Jain83a6cc22016-06-28 14:34:17 +05304607 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304608 bytes_to_write);
4609
4610 /*Convert written bytes in audio flinger format*/
4611 if (ret > 0)
4612 ret = ((ret * format_to_bitwidth_table[out->format]) /
4613 format_to_bitwidth_table[dst_format]);
4614 }
4615 } else
4616 ret = compress_write(out->compr, buffer, bytes);
4617
Zhou Songc9672822017-08-16 16:01:39 +08004618 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4619 update_frames_written(out, bytes);
4620
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304621 if (ret < 0)
4622 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08004623 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304624 /*msg to cb thread only if non blocking write is enabled*/
4625 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304626 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004627 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304628 } else if (-ENETRESET == ret) {
4629 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304630 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304631 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304632 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004633 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304634 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004635 }
Ashish Jain5106d362016-05-11 19:23:33 +05304636
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304637 /* Call compr start only when non-zero bytes of data is there to be rendered */
4638 if (!out->playback_started && ret > 0) {
4639 int status = compress_start(out->compr);
4640 if (status < 0) {
4641 ret = status;
4642 ALOGE("%s: compr start failed with err %d", __func__, errno);
4643 goto exit;
4644 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004645 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004646 out->playback_started = 1;
4647 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004648
4649 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4650 popcount(out->channel_mask),
4651 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004652 }
4653 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004654 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004655 return ret;
4656 } else {
4657 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004658 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004659 if (out->muted)
4660 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004661 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
4662 __func__, frames, frame_size, bytes_to_write);
4663
4664 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
4665 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4666 int16_t *src = (int16_t *)buffer;
4667 int16_t *dst = (int16_t *)buffer;
4668
4669 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
4670 out->format != AUDIO_FORMAT_PCM_16_BIT,
4671 "out_write called for incall music use case with wrong properties");
4672
4673 /*
4674 * FIXME: this can be removed once audio flinger mixer supports
4675 * mono output
4676 */
4677
4678 /*
4679 * Code below goes over each frame in the buffer and adds both
4680 * L and R samples and then divides by 2 to convert to mono
4681 */
4682 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
4683 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
4684 }
4685 bytes_to_write /= 2;
4686 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004687
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304688 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004689
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004690 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004691
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004692 if (out->config.rate)
4693 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4694 out->config.rate;
4695
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004696 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004697 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4698
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004699 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004700 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004701 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304702 out->convert_buffer != NULL) {
4703
4704 memcpy_by_audio_format(out->convert_buffer,
4705 out->hal_op_format,
4706 buffer,
4707 out->hal_ip_format,
4708 out->config.period_size * out->config.channels);
4709
4710 ret = pcm_write(out->pcm, out->convert_buffer,
4711 (out->config.period_size *
4712 out->config.channels *
4713 format_to_bitwidth_table[out->hal_op_format]));
4714 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304715 /*
4716 * To avoid underrun in DSP when the application is not pumping
4717 * data at required rate, check for the no. of bytes and ignore
4718 * pcm_write if it is less than actual buffer size.
4719 * It is a work around to a change in compress VOIP driver.
4720 */
4721 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4722 bytes < (out->config.period_size * out->config.channels *
4723 audio_bytes_per_sample(out->format))) {
4724 size_t voip_buf_size =
4725 out->config.period_size * out->config.channels *
4726 audio_bytes_per_sample(out->format);
4727 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4728 __func__, bytes, voip_buf_size);
4729 usleep(((uint64_t)voip_buf_size - bytes) *
4730 1000000 / audio_stream_out_frame_size(stream) /
4731 out_get_sample_rate(&out->stream.common));
4732 ret = 0;
4733 } else
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004734 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304735 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004736
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004737 release_out_focus(out);
4738
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304739 if (ret < 0)
4740 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004741 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304742 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004743 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004744 }
4745
4746exit:
Zhou Songc9672822017-08-16 16:01:39 +08004747 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304748 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304749 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304750 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004751 pthread_mutex_unlock(&out->lock);
4752
4753 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004754 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004755 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304756 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304757 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304758 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304759 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304760 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304761 out->standby = true;
4762 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304763 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304764 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4765 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4766 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004767
4768 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05304769 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004770 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004771 return ret;
4772 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004773 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004774 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004775 return bytes;
4776}
4777
4778static int out_get_render_position(const struct audio_stream_out *stream,
4779 uint32_t *dsp_frames)
4780{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004781 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004782
4783 if (dsp_frames == NULL)
4784 return -EINVAL;
4785
4786 *dsp_frames = 0;
4787 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004788 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304789
4790 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4791 * this operation and adev_close_output_stream(where out gets reset).
4792 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304793 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004794 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05304795 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004796 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304797 return 0;
4798 }
4799
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004800 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304801 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304802 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004803 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304804 if (ret < 0)
4805 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004806 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304807 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004808 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304809 if (-ENETRESET == ret) {
4810 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304811 out->card_status = CARD_STATUS_OFFLINE;
4812 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304813 } else if(ret < 0) {
4814 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304815 ret = -EINVAL;
4816 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304817 /*
4818 * Handle corner case where compress session is closed during SSR
4819 * and timestamp is queried
4820 */
4821 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304822 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304823 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304824 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004825 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05304826 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304827 pthread_mutex_unlock(&out->lock);
4828 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004829 } else if (audio_is_linear_pcm(out->format)) {
4830 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004831 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08004832 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004833 } else
4834 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004835}
4836
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004837static int out_add_audio_effect(const struct audio_stream *stream __unused,
4838 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004839{
4840 return 0;
4841}
4842
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004843static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4844 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004845{
4846 return 0;
4847}
4848
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004849static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4850 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004851{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304852 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004853}
4854
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004855static int out_get_presentation_position(const struct audio_stream_out *stream,
4856 uint64_t *frames, struct timespec *timestamp)
4857{
4858 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05304859 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07004860 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004861
Ashish Jain5106d362016-05-11 19:23:33 +05304862 /* below piece of code is not guarded against any lock because audioFliner serializes
4863 * this operation and adev_close_output_stream( where out gets reset).
4864 */
4865 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304866 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004867 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05304868 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4869 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4870 return 0;
4871 }
4872
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004873 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004874
Ashish Jain5106d362016-05-11 19:23:33 +05304875 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4876 ret = compress_get_tstamp(out->compr, &dsp_frames,
4877 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004878 // Adjustment accounts for A2dp encoder latency with offload usecases
4879 // Note: Encoder latency is returned in ms.
4880 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4881 unsigned long offset =
4882 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4883 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4884 }
Ashish Jain5106d362016-05-11 19:23:33 +05304885 ALOGVV("%s rendered frames %ld sample_rate %d",
4886 __func__, dsp_frames, out->sample_rate);
4887 *frames = dsp_frames;
4888 if (ret < 0)
4889 ret = -errno;
4890 if (-ENETRESET == ret) {
4891 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304892 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304893 ret = -EINVAL;
4894 } else
4895 ret = 0;
4896 /* this is the best we can do */
4897 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07004898 } else {
4899 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08004900 unsigned int avail;
4901 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
4902 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
4903 int64_t signed_frames = out->written - kernel_buffer_size + avail;
4904 // This adjustment accounts for buffering after app processor.
4905 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07004906 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08004907 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07004908
Weiyin Jiangd4633762018-03-16 12:05:03 +08004909 // Adjustment accounts for A2dp encoder latency with non offload usecases
4910 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
4911 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4912 signed_frames -=
4913 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4914 }
4915
4916 // It would be unusual for this value to be negative, but check just in case ...
4917 if (signed_frames >= 0) {
4918 *frames = signed_frames;
4919 ret = 0;
4920 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004921 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304922 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304923 *frames = out->written;
4924 clock_gettime(CLOCK_MONOTONIC, timestamp);
4925 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004926 }
4927 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004928 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004929 return ret;
4930}
4931
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004932static int out_set_callback(struct audio_stream_out *stream,
4933 stream_callback_t callback, void *cookie)
4934{
4935 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004936 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004937
4938 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004939 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004940 out->client_callback = callback;
4941 out->client_cookie = cookie;
4942 if (out->adsp_hdlr_stream_handle) {
4943 ret = audio_extn_adsp_hdlr_stream_set_callback(
4944 out->adsp_hdlr_stream_handle,
4945 callback,
4946 cookie);
4947 if (ret)
4948 ALOGW("%s:adsp hdlr callback registration failed %d",
4949 __func__, ret);
4950 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004951 pthread_mutex_unlock(&out->lock);
4952 return 0;
4953}
4954
4955static int out_pause(struct audio_stream_out* stream)
4956{
4957 struct stream_out *out = (struct stream_out *)stream;
4958 int status = -ENOSYS;
4959 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004960 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004961 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004962 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004963 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304964 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304965 status = compress_pause(out->compr);
4966
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004967 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004968
Mingming Yin21854652016-04-13 11:54:02 -07004969 if (audio_extn_passthru_is_active()) {
4970 ALOGV("offload use case, pause passthru");
4971 audio_extn_passthru_on_pause(out);
4972 }
4973
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304974 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004975 audio_extn_dts_notify_playback_state(out->usecase, 0,
4976 out->sample_rate, popcount(out->channel_mask),
4977 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004978 }
4979 pthread_mutex_unlock(&out->lock);
4980 }
4981 return status;
4982}
4983
4984static int out_resume(struct audio_stream_out* stream)
4985{
4986 struct stream_out *out = (struct stream_out *)stream;
4987 int status = -ENOSYS;
4988 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004989 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004990 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004991 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004992 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004993 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304994 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304995 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004996 }
4997 if (!status) {
4998 out->offload_state = OFFLOAD_STATE_PLAYING;
4999 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305000 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005001 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5002 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005003 }
5004 pthread_mutex_unlock(&out->lock);
5005 }
5006 return status;
5007}
5008
5009static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5010{
5011 struct stream_out *out = (struct stream_out *)stream;
5012 int status = -ENOSYS;
5013 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005014 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005015 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005016 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5017 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5018 else
5019 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5020 pthread_mutex_unlock(&out->lock);
5021 }
5022 return status;
5023}
5024
5025static int out_flush(struct audio_stream_out* stream)
5026{
5027 struct stream_out *out = (struct stream_out *)stream;
5028 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005029 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005030 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005031 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005032 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5033 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005034 } else {
5035 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5036 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005037 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005038 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005039 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005040 return 0;
5041 }
5042 return -ENOSYS;
5043}
5044
Haynes Mathew George16081042017-05-31 17:16:49 -07005045static int out_stop(const struct audio_stream_out* stream)
5046{
5047 struct stream_out *out = (struct stream_out *)stream;
5048 struct audio_device *adev = out->dev;
5049 int ret = -ENOSYS;
5050
5051 ALOGV("%s", __func__);
5052 pthread_mutex_lock(&adev->lock);
5053 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5054 out->playback_started && out->pcm != NULL) {
5055 pcm_stop(out->pcm);
5056 ret = stop_output_stream(out);
5057 out->playback_started = false;
5058 }
5059 pthread_mutex_unlock(&adev->lock);
5060 return ret;
5061}
5062
5063static int out_start(const struct audio_stream_out* stream)
5064{
5065 struct stream_out *out = (struct stream_out *)stream;
5066 struct audio_device *adev = out->dev;
5067 int ret = -ENOSYS;
5068
5069 ALOGV("%s", __func__);
5070 pthread_mutex_lock(&adev->lock);
5071 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5072 !out->playback_started && out->pcm != NULL) {
5073 ret = start_output_stream(out);
5074 if (ret == 0) {
5075 out->playback_started = true;
5076 }
5077 }
5078 pthread_mutex_unlock(&adev->lock);
5079 return ret;
5080}
5081
5082/*
5083 * Modify config->period_count based on min_size_frames
5084 */
5085static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5086{
5087 int periodCountRequested = (min_size_frames + config->period_size - 1)
5088 / config->period_size;
5089 int periodCount = MMAP_PERIOD_COUNT_MIN;
5090
5091 ALOGV("%s original config.period_size = %d config.period_count = %d",
5092 __func__, config->period_size, config->period_count);
5093
5094 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5095 periodCount *= 2;
5096 }
5097 config->period_count = periodCount;
5098
5099 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5100}
5101
5102static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5103 int32_t min_size_frames,
5104 struct audio_mmap_buffer_info *info)
5105{
5106 struct stream_out *out = (struct stream_out *)stream;
5107 struct audio_device *adev = out->dev;
5108 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005109 unsigned int offset1 = 0;
5110 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005111 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005112 uint32_t mmap_size;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005113 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005114
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005115 ALOGD("%s", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07005116 pthread_mutex_lock(&adev->lock);
5117
5118 if (info == NULL || min_size_frames == 0) {
5119 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5120 ret = -EINVAL;
5121 goto exit;
5122 }
5123 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5124 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5125 ret = -ENOSYS;
5126 goto exit;
5127 }
5128 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5129 if (out->pcm_device_id < 0) {
5130 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5131 __func__, out->pcm_device_id, out->usecase);
5132 ret = -EINVAL;
5133 goto exit;
5134 }
5135
5136 adjust_mmap_period_count(&out->config, min_size_frames);
5137
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005138 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005139 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5140 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5141 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
5142 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5143 step = "open";
5144 ret = -ENODEV;
5145 goto exit;
5146 }
5147 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5148 if (ret < 0) {
5149 step = "begin";
5150 goto exit;
5151 }
5152 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005153 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005154 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005155 ret = platform_get_mmap_data_fd(adev->platform,
5156 out->pcm_device_id, 0 /*playback*/,
5157 &info->shared_memory_fd,
5158 &mmap_size);
5159 if (ret < 0) {
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005160 // Fall back to non exclusive mode
5161 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5162 } else {
5163 if (mmap_size < buffer_size) {
5164 step = "mmap";
5165 goto exit;
5166 }
5167 // FIXME: indicate exclusive mode support by returning a negative buffer size
5168 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005169 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005170 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07005171
5172 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5173 if (ret < 0) {
5174 step = "commit";
5175 goto exit;
5176 }
5177
5178 out->standby = false;
5179 ret = 0;
5180
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005181 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005182 __func__, info->shared_memory_address, info->buffer_size_frames);
5183
5184exit:
5185 if (ret != 0) {
5186 if (out->pcm == NULL) {
5187 ALOGE("%s: %s - %d", __func__, step, ret);
5188 } else {
5189 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5190 pcm_close(out->pcm);
5191 out->pcm = NULL;
5192 }
5193 }
5194 pthread_mutex_unlock(&adev->lock);
5195 return ret;
5196}
5197
5198static int out_get_mmap_position(const struct audio_stream_out *stream,
5199 struct audio_mmap_position *position)
5200{
5201 struct stream_out *out = (struct stream_out *)stream;
5202 ALOGVV("%s", __func__);
5203 if (position == NULL) {
5204 return -EINVAL;
5205 }
5206 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005207 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005208 return -ENOSYS;
5209 }
5210 if (out->pcm == NULL) {
5211 return -ENOSYS;
5212 }
5213
5214 struct timespec ts = { 0, 0 };
5215 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5216 if (ret < 0) {
5217 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5218 return ret;
5219 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005220 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005221 return 0;
5222}
5223
5224
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005225/** audio_stream_in implementation **/
5226static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5227{
5228 struct stream_in *in = (struct stream_in *)stream;
5229
5230 return in->config.rate;
5231}
5232
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005233static int in_set_sample_rate(struct audio_stream *stream __unused,
5234 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005235{
5236 return -ENOSYS;
5237}
5238
5239static size_t in_get_buffer_size(const struct audio_stream *stream)
5240{
5241 struct stream_in *in = (struct stream_in *)stream;
5242
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005243 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5244 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005245 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5246 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 -07005247 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5248 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305249 else if(audio_extn_cin_attached_usecase(in->usecase))
5250 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005251
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005252 return in->config.period_size * in->af_period_multiplier *
5253 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005254}
5255
5256static uint32_t in_get_channels(const struct audio_stream *stream)
5257{
5258 struct stream_in *in = (struct stream_in *)stream;
5259
5260 return in->channel_mask;
5261}
5262
5263static audio_format_t in_get_format(const struct audio_stream *stream)
5264{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005265 struct stream_in *in = (struct stream_in *)stream;
5266
5267 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005268}
5269
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005270static int in_set_format(struct audio_stream *stream __unused,
5271 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005272{
5273 return -ENOSYS;
5274}
5275
5276static int in_standby(struct audio_stream *stream)
5277{
5278 struct stream_in *in = (struct stream_in *)stream;
5279 struct audio_device *adev = in->dev;
5280 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305281 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5282 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005283 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305284
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005285 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005286 if (!in->standby && in->is_st_session) {
5287 ALOGD("%s: sound trigger pcm stop lab", __func__);
5288 audio_extn_sound_trigger_stop_lab(in);
5289 in->standby = 1;
5290 }
5291
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005292 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005293 if (adev->adm_deregister_stream)
5294 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5295
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005296 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005297 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005298 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005299 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005300 voice_extn_compress_voip_close_input_stream(stream);
5301 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005302 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5303 do_stop = in->capture_started;
5304 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005305 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305306 if (audio_extn_cin_attached_usecase(in->usecase))
5307 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005308 }
5309
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005310 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005311 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005312 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005313 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005314 in->pcm = NULL;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005315 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005316
5317 if (do_stop)
5318 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005319 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005320 }
5321 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005322 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005323 return status;
5324}
5325
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005326static int in_dump(const struct audio_stream *stream __unused,
5327 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005328{
5329 return 0;
5330}
5331
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305332static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5333{
5334 if (!stream || !parms)
5335 return;
5336
5337 struct stream_in *in = (struct stream_in *)stream;
5338 struct audio_device *adev = in->dev;
5339
5340 card_status_t status;
5341 int card;
5342 if (parse_snd_card_status(parms, &card, &status) < 0)
5343 return;
5344
5345 pthread_mutex_lock(&adev->lock);
5346 bool valid_cb = (card == adev->snd_card);
5347 pthread_mutex_unlock(&adev->lock);
5348
5349 if (!valid_cb)
5350 return;
5351
5352 lock_input_stream(in);
5353 if (in->card_status != status)
5354 in->card_status = status;
5355 pthread_mutex_unlock(&in->lock);
5356
5357 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5358 use_case_table[in->usecase],
5359 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5360
5361 // a better solution would be to report error back to AF and let
5362 // it put the stream to standby
5363 if (status == CARD_STATUS_OFFLINE)
5364 in_standby(&in->stream.common);
5365
5366 return;
5367}
5368
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005369static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5370{
5371 struct stream_in *in = (struct stream_in *)stream;
5372 struct audio_device *adev = in->dev;
5373 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005374 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005375 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005376
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305377 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005378 parms = str_parms_create_str(kvpairs);
5379
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305380 if (!parms)
5381 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005382 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005383 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005384
5385 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5386 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005387 val = atoi(value);
5388 /* no audio source uses val == 0 */
5389 if ((in->source != val) && (val != 0)) {
5390 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005391 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5392 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5393 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005394 (in->config.rate == 8000 || in->config.rate == 16000 ||
5395 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005396 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005397 err = voice_extn_compress_voip_open_input_stream(in);
5398 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005399 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005400 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005401 }
5402 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005403 }
5404 }
5405
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005406 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5407 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005408 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005409 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5410
5411 // Workaround: If routing to an non existing usb device, fail gracefully
5412 // The routing request will otherwise block during 10 second
5413 int card;
5414 if (audio_is_usb_in_device(val) &&
5415 (card = get_alive_usb_card(parms)) >= 0) {
5416
5417 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5418 ret = -ENOSYS;
5419 } else {
5420
5421 in->device = val;
5422 /* If recording is in progress, change the tx device to new device */
5423 if (!in->standby && !in->is_st_session) {
5424 ALOGV("update input routing change");
5425 // inform adm before actual routing to prevent glitches.
5426 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005427 adev->adm_on_routing_change(adev->adm_data,
5428 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005429 ret = select_devices(adev, in->usecase);
5430 }
5431 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005432 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005433 }
5434 }
5435
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305436 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5437 if (err >= 0) {
5438 strlcpy(in->profile, value, sizeof(in->profile));
5439 ALOGV("updating stream profile with value '%s'", in->profile);
5440 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5441 &adev->streams_input_cfg_list,
5442 in->device, in->flags, in->format,
5443 in->sample_rate, in->bit_width,
5444 in->profile, &in->app_type_cfg);
5445 }
5446
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005447 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005448 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005449
5450 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305451error:
Eric Laurent994a6932013-07-17 11:51:42 -07005452 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005453 return ret;
5454}
5455
5456static char* in_get_parameters(const struct audio_stream *stream,
5457 const char *keys)
5458{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005459 struct stream_in *in = (struct stream_in *)stream;
5460 struct str_parms *query = str_parms_create_str(keys);
5461 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005462 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005463
5464 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005465 if (reply) {
5466 str_parms_destroy(reply);
5467 }
5468 if (query) {
5469 str_parms_destroy(query);
5470 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005471 ALOGE("in_get_parameters: failed to create query or reply");
5472 return NULL;
5473 }
5474
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005475 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005476
5477 voice_extn_in_get_parameters(in, query, reply);
5478
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005479 stream_get_parameter_channels(query, reply,
5480 &in->supported_channel_masks[0]);
5481 stream_get_parameter_formats(query, reply,
5482 &in->supported_formats[0]);
5483 stream_get_parameter_rates(query, reply,
5484 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005485 str = str_parms_to_str(reply);
5486 str_parms_destroy(query);
5487 str_parms_destroy(reply);
5488
5489 ALOGV("%s: exit: returns - %s", __func__, str);
5490 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005491}
5492
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005493static int in_set_gain(struct audio_stream_in *stream __unused,
5494 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005495{
5496 return 0;
5497}
5498
5499static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5500 size_t bytes)
5501{
5502 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305503
5504 if (in == NULL) {
5505 ALOGE("%s: stream_in ptr is NULL", __func__);
5506 return -EINVAL;
5507 }
5508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005509 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305510 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305511 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005512
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005513 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305514
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005515 if (in->is_st_session) {
5516 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5517 /* Read from sound trigger HAL */
5518 audio_extn_sound_trigger_read(in, buffer, bytes);
5519 pthread_mutex_unlock(&in->lock);
5520 return bytes;
5521 }
5522
Haynes Mathew George16081042017-05-31 17:16:49 -07005523 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5524 ret = -ENOSYS;
5525 goto exit;
5526 }
5527
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005528 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005529 pthread_mutex_lock(&adev->lock);
5530 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5531 ret = voice_extn_compress_voip_start_input_stream(in);
5532 else
5533 ret = start_input_stream(in);
5534 pthread_mutex_unlock(&adev->lock);
5535 if (ret != 0) {
5536 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005537 }
5538 in->standby = 0;
5539 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005540
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005541 // what's the duration requested by the client?
5542 long ns = 0;
5543
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305544 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005545 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5546 in->config.rate;
5547
5548 request_in_focus(in, ns);
5549 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005550
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305551 if (audio_extn_cin_attached_usecase(in->usecase)) {
5552 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5553 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305554 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005555 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305556 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005557 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005558 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005559 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005560 } else if (audio_extn_ffv_get_stream() == in) {
5561 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305562 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005563 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305564 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5565 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5566 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5567 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305568 ret = -EINVAL;
5569 goto exit;
5570 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305571 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305572 ret = -errno;
5573 }
5574 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305575 /* bytes read is always set to bytes for non compress usecases */
5576 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005577 }
5578
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005579 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005580
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005581 /*
5582 * Instead of writing zeroes here, we could trust the hardware
5583 * to always provide zeroes when muted.
5584 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305585 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5586 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005587 memset(buffer, 0, bytes);
5588
5589exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005590 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305591 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005592 pthread_mutex_unlock(&in->lock);
5593
5594 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305595 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305596 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305597 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305598 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305599 in->standby = true;
5600 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305601 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5602 bytes_read = bytes;
5603 memset(buffer, 0, bytes);
5604 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005605 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005606 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305607 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305608 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005609 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305610 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005611}
5612
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005613static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005614{
5615 return 0;
5616}
5617
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005618static int add_remove_audio_effect(const struct audio_stream *stream,
5619 effect_handle_t effect,
5620 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005621{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005622 struct stream_in *in = (struct stream_in *)stream;
5623 int status = 0;
5624 effect_descriptor_t desc;
5625
5626 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005627 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5628
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005629 if (status != 0)
5630 return status;
5631
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005632 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005633 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08005634 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5635 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005636 in->enable_aec != enable &&
5637 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5638 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005639 if (!in->standby) {
5640 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5641 select_devices(in->dev, in->usecase);
5642 }
5643
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005644 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005645 if (in->enable_ns != enable &&
5646 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5647 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005648 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08005649 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5650 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005651 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5652 select_devices(in->dev, in->usecase);
5653 } else
5654 select_devices(in->dev, in->usecase);
5655 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005656 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005657 pthread_mutex_unlock(&in->dev->lock);
5658 pthread_mutex_unlock(&in->lock);
5659
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005660 return 0;
5661}
5662
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005663static int in_add_audio_effect(const struct audio_stream *stream,
5664 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005665{
Eric Laurent994a6932013-07-17 11:51:42 -07005666 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005667 return add_remove_audio_effect(stream, effect, true);
5668}
5669
5670static int in_remove_audio_effect(const struct audio_stream *stream,
5671 effect_handle_t effect)
5672{
Eric Laurent994a6932013-07-17 11:51:42 -07005673 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005674 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005675}
5676
Haynes Mathew George16081042017-05-31 17:16:49 -07005677static int in_stop(const struct audio_stream_in* stream)
5678{
5679 struct stream_in *in = (struct stream_in *)stream;
5680 struct audio_device *adev = in->dev;
5681
5682 int ret = -ENOSYS;
5683 ALOGV("%s", __func__);
5684 pthread_mutex_lock(&adev->lock);
5685 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5686 in->capture_started && in->pcm != NULL) {
5687 pcm_stop(in->pcm);
5688 ret = stop_input_stream(in);
5689 in->capture_started = false;
5690 }
5691 pthread_mutex_unlock(&adev->lock);
5692 return ret;
5693}
5694
5695static int in_start(const struct audio_stream_in* stream)
5696{
5697 struct stream_in *in = (struct stream_in *)stream;
5698 struct audio_device *adev = in->dev;
5699 int ret = -ENOSYS;
5700
5701 ALOGV("%s in %p", __func__, in);
5702 pthread_mutex_lock(&adev->lock);
5703 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5704 !in->capture_started && in->pcm != NULL) {
5705 if (!in->capture_started) {
5706 ret = start_input_stream(in);
5707 if (ret == 0) {
5708 in->capture_started = true;
5709 }
5710 }
5711 }
5712 pthread_mutex_unlock(&adev->lock);
5713 return ret;
5714}
5715
5716static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5717 int32_t min_size_frames,
5718 struct audio_mmap_buffer_info *info)
5719{
5720 struct stream_in *in = (struct stream_in *)stream;
5721 struct audio_device *adev = in->dev;
5722 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005723 unsigned int offset1 = 0;
5724 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005725 const char *step = "";
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005726 uint32_t mmap_size = 0;
5727 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005728
5729 pthread_mutex_lock(&adev->lock);
5730 ALOGV("%s in %p", __func__, in);
5731
5732 if (info == NULL || min_size_frames == 0) {
5733 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5734 ret = -EINVAL;
5735 goto exit;
5736 }
5737 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5738 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5739 ALOGV("%s in %p", __func__, in);
5740 ret = -ENOSYS;
5741 goto exit;
5742 }
5743 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5744 if (in->pcm_device_id < 0) {
5745 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5746 __func__, in->pcm_device_id, in->usecase);
5747 ret = -EINVAL;
5748 goto exit;
5749 }
5750
5751 adjust_mmap_period_count(&in->config, min_size_frames);
5752
5753 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5754 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5755 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5756 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
5757 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5758 step = "open";
5759 ret = -ENODEV;
5760 goto exit;
5761 }
5762
5763 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5764 if (ret < 0) {
5765 step = "begin";
5766 goto exit;
5767 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005768
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005769 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5770 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
5771 info->burst_size_frames = in->config.period_size;
5772 ret = platform_get_mmap_data_fd(adev->platform,
5773 in->pcm_device_id, 1 /*capture*/,
5774 &info->shared_memory_fd,
5775 &mmap_size);
5776 if (ret < 0) {
5777 // Fall back to non exclusive mode
5778 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
5779 } else {
5780 if (mmap_size < buffer_size) {
5781 step = "mmap";
5782 goto exit;
5783 }
5784 // FIXME: indicate exclusive mode support by returning a negative buffer size
5785 info->buffer_size_frames *= -1;
5786 }
5787
5788 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07005789
5790 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
5791 if (ret < 0) {
5792 step = "commit";
5793 goto exit;
5794 }
5795
5796 in->standby = false;
5797 ret = 0;
5798
5799 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5800 __func__, info->shared_memory_address, info->buffer_size_frames);
5801
5802exit:
5803 if (ret != 0) {
5804 if (in->pcm == NULL) {
5805 ALOGE("%s: %s - %d", __func__, step, ret);
5806 } else {
5807 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
5808 pcm_close(in->pcm);
5809 in->pcm = NULL;
5810 }
5811 }
5812 pthread_mutex_unlock(&adev->lock);
5813 return ret;
5814}
5815
5816static int in_get_mmap_position(const struct audio_stream_in *stream,
5817 struct audio_mmap_position *position)
5818{
5819 struct stream_in *in = (struct stream_in *)stream;
5820 ALOGVV("%s", __func__);
5821 if (position == NULL) {
5822 return -EINVAL;
5823 }
5824 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
5825 return -ENOSYS;
5826 }
5827 if (in->pcm == NULL) {
5828 return -ENOSYS;
5829 }
5830 struct timespec ts = { 0, 0 };
5831 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
5832 if (ret < 0) {
5833 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
5834 return ret;
5835 }
5836 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
5837 return 0;
5838}
5839
Naresh Tannirudcb47c52018-06-25 16:23:32 +05305840static int in_get_active_microphones(const struct audio_stream_in *stream,
5841 struct audio_microphone_characteristic_t *mic_array,
5842 size_t *mic_count) {
5843 struct stream_in *in = (struct stream_in *)stream;
5844 struct audio_device *adev = in->dev;
5845 ALOGVV("%s", __func__);
5846
5847 lock_input_stream(in);
5848 pthread_mutex_lock(&adev->lock);
5849 int ret = platform_get_active_microphones(adev->platform,
5850 audio_channel_count_from_in_mask(in->channel_mask),
5851 in->usecase, mic_array, mic_count);
5852 pthread_mutex_unlock(&adev->lock);
5853 pthread_mutex_unlock(&in->lock);
5854
5855 return ret;
5856}
5857
5858static int adev_get_microphones(const struct audio_hw_device *dev,
5859 struct audio_microphone_characteristic_t *mic_array,
5860 size_t *mic_count) {
5861 struct audio_device *adev = (struct audio_device *)dev;
5862 ALOGVV("%s", __func__);
5863
5864 pthread_mutex_lock(&adev->lock);
5865 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
5866 pthread_mutex_unlock(&adev->lock);
5867
5868 return ret;
5869}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305870int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07005871 audio_io_handle_t handle,
5872 audio_devices_t devices,
5873 audio_output_flags_t flags,
5874 struct audio_config *config,
5875 struct audio_stream_out **stream_out,
5876 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005877{
5878 struct audio_device *adev = (struct audio_device *)dev;
5879 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305880 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005881 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005882 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05305883 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005884 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
5885 bool is_usb_dev = audio_is_usb_out_device(devices) &&
5886 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
5887 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005888
kunleizdff872d2018-08-20 14:40:33 +08005889 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08005890 is_usb_dev = false;
5891 devices = AUDIO_DEVICE_OUT_SPEAKER;
5892 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
5893 __func__, devices);
5894 }
5895
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005896 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305897
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005898 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
5899
Mingming Yin3a941d42016-02-17 18:08:05 -08005900 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
5901 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305902 devices, flags, &out->stream);
5903
5904
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005905 if (!out) {
5906 return -ENOMEM;
5907 }
5908
Haynes Mathew George204045b2015-02-25 20:32:03 -08005909 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005910 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305911 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08005912 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08005913 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5914
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005915 if (devices == AUDIO_DEVICE_NONE)
5916 devices = AUDIO_DEVICE_OUT_SPEAKER;
5917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005918 out->flags = flags;
5919 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07005920 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07005921 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005922 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05305923 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05305924 if (out->channel_mask == AUDIO_CHANNEL_NONE)
5925 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
5926 else
5927 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07005928 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005929 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08005930 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305931 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305932 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305933 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005934 out->hal_output_suspend_supported = 0;
5935 out->dynamic_pm_qos_config_supported = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005936
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05305937 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05305938 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07005939 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
5940
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005941 if (audio_is_linear_pcm(out->format) &&
5942 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
5943 pthread_mutex_lock(&adev->lock);
5944 if (is_hdmi) {
5945 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
5946 ret = read_hdmi_sink_caps(out);
5947 } else if (is_usb_dev) {
5948 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
5949 &config->format,
5950 &out->supported_formats[0],
5951 MAX_SUPPORTED_FORMATS,
5952 &config->channel_mask,
5953 &out->supported_channel_masks[0],
5954 MAX_SUPPORTED_CHANNEL_MASKS,
5955 &config->sample_rate,
5956 &out->supported_sample_rates[0],
5957 MAX_SUPPORTED_SAMPLE_RATES);
5958 ALOGV("plugged dev USB ret %d", ret);
5959 } else {
5960 ret = -1;
5961 }
5962 pthread_mutex_unlock(&adev->lock);
5963 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005964 if (ret == -ENOSYS) {
5965 /* ignore and go with default */
5966 ret = 0;
5967 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005968 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08005969 goto error_open;
5970 }
5971 }
5972 }
5973
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005974 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07005975#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005976 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5977 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
5978 out->sample_rate == 32000 || out->sample_rate == 48000)) {
5979 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
5980 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
5981 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5982
5983 out->config = default_pcm_config_voip_copp;
5984 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5985 out->config.rate = out->sample_rate;
5986
5987#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05305988 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005989 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08005990 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005991 ret = voice_extn_compress_voip_open_output_stream(out);
5992 if (ret != 0) {
5993 ALOGE("%s: Compress voip output cannot be opened, error:%d",
5994 __func__, ret);
5995 goto error_open;
5996 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005997#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005998 } else if (audio_is_linear_pcm(out->format) &&
5999 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6000 out->channel_mask = config->channel_mask;
6001 out->sample_rate = config->sample_rate;
6002 out->format = config->format;
6003 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6004 // does this change?
6005 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6006 out->config.rate = config->sample_rate;
6007 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6008 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6009 audio_bytes_per_sample(config->format));
6010 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006011 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306012 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306013 pthread_mutex_lock(&adev->lock);
6014 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6015 pthread_mutex_unlock(&adev->lock);
6016
6017 // reject offload during card offline to allow
6018 // fallback to s/w paths
6019 if (offline) {
6020 ret = -ENODEV;
6021 goto error_open;
6022 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006023
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006024 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6025 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6026 ALOGE("%s: Unsupported Offload information", __func__);
6027 ret = -EINVAL;
6028 goto error_open;
6029 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006030
Atul Khare3fa6e542017-08-09 00:56:17 +05306031 if (config->offload_info.format == 0)
6032 config->offload_info.format = config->format;
6033 if (config->offload_info.sample_rate == 0)
6034 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006035
Mingming Yin90310102013-11-13 16:57:00 -08006036 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306037 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006038 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006039 ret = -EINVAL;
6040 goto error_open;
6041 }
6042
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006043 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6044 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6045 (audio_extn_passthru_is_passthrough_stream(out)) &&
6046 !((config->sample_rate == 48000) ||
6047 (config->sample_rate == 96000) ||
6048 (config->sample_rate == 192000))) {
6049 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6050 __func__, config->sample_rate, config->offload_info.format);
6051 ret = -EINVAL;
6052 goto error_open;
6053 }
6054
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006055 out->compr_config.codec = (struct snd_codec *)
6056 calloc(1, sizeof(struct snd_codec));
6057
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006058 if (!out->compr_config.codec) {
6059 ret = -ENOMEM;
6060 goto error_open;
6061 }
6062
Dhananjay Kumarac341582017-02-23 23:42:25 +05306063 out->stream.pause = out_pause;
6064 out->stream.resume = out_resume;
6065 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306066 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306067 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006068 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306069 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006070 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306071 } else {
6072 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6073 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006074 }
vivek mehta446c3962015-09-14 10:57:35 -07006075
6076 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006077 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6078 config->format == 0 && config->sample_rate == 0 &&
6079 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006080 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006081 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6082 } else {
6083 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6084 ret = -EEXIST;
6085 goto error_open;
6086 }
vivek mehta446c3962015-09-14 10:57:35 -07006087 }
6088
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006089 if (config->offload_info.channel_mask)
6090 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006091 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006092 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006093 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006094 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306095 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006096 ret = -EINVAL;
6097 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006098 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006099
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006100 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006101 out->sample_rate = config->offload_info.sample_rate;
6102
Mingming Yin3ee55c62014-08-04 14:23:35 -07006103 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006104
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306105 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306106 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306107 audio_extn_dolby_send_ddp_endp_params(adev);
6108 audio_extn_dolby_set_dmid(adev);
6109 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006110
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006111 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006112 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006113 out->compr_config.codec->bit_rate =
6114 config->offload_info.bit_rate;
6115 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306116 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006117 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306118 /* Update bit width only for non passthrough usecases.
6119 * For passthrough usecases, the output will always be opened @16 bit
6120 */
6121 if (!audio_extn_passthru_is_passthrough_stream(out))
6122 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306123
6124 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6125 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6126 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6127
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006128 /*TODO: Do we need to change it for passthrough */
6129 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006130
Manish Dewangana6fc5442015-08-24 20:30:31 +05306131 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6132 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306133 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306134 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306135 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6136 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306137
6138 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6139 AUDIO_FORMAT_PCM) {
6140
6141 /*Based on platform support, configure appropriate alsa format for corresponding
6142 *hal input format.
6143 */
6144 out->compr_config.codec->format = hal_format_to_alsa(
6145 config->offload_info.format);
6146
Ashish Jain83a6cc22016-06-28 14:34:17 +05306147 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306148 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306149 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306150
Dhananjay Kumarac341582017-02-23 23:42:25 +05306151 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306152 *hal input format and alsa format might differ based on platform support.
6153 */
6154 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306155 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306156
6157 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6158
6159 /* Check if alsa session is configured with the same format as HAL input format,
6160 * if not then derive correct fragment size needed to accomodate the
6161 * conversion of HAL input format to alsa format.
6162 */
6163 audio_extn_utils_update_direct_pcm_fragment_size(out);
6164
6165 /*if hal input and output fragment size is different this indicates HAL input format is
6166 *not same as the alsa format
6167 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306168 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306169 /*Allocate a buffer to convert input data to the alsa configured format.
6170 *size of convert buffer is equal to the size required to hold one fragment size
6171 *worth of pcm data, this is because flinger does not write more than fragment_size
6172 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306173 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6174 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306175 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6176 ret = -ENOMEM;
6177 goto error_open;
6178 }
6179 }
6180 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6181 out->compr_config.fragment_size =
6182 audio_extn_passthru_get_buffer_size(&config->offload_info);
6183 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6184 } else {
6185 out->compr_config.fragment_size =
6186 platform_get_compress_offload_buffer_size(&config->offload_info);
6187 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6188 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006189
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306190 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6191 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6192 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006193 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306194 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006195
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306196 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6197 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6198 }
6199
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006200 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6201 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006202
Manish Dewangan69426c82017-01-30 17:35:36 +05306203 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6204 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6205 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6206 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6207 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6208 } else {
6209 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6210 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006211
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306212 memset(&out->channel_map_param, 0,
6213 sizeof(struct audio_out_channel_map_param));
6214
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006215 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306216 out->send_next_track_params = false;
6217 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006218 out->offload_state = OFFLOAD_STATE_IDLE;
6219 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006220 out->writeAt.tv_sec = 0;
6221 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006222
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006223 audio_extn_dts_create_state_notifier_node(out->usecase);
6224
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006225 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6226 __func__, config->offload_info.version,
6227 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306228
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306229 /* Check if DSD audio format is supported in codec
6230 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306231 */
6232
6233 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306234 (!platform_check_codec_dsd_support(adev->platform) ||
6235 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306236 ret = -EINVAL;
6237 goto error_open;
6238 }
6239
Ashish Jain5106d362016-05-11 19:23:33 +05306240 /* Disable gapless if any of the following is true
6241 * passthrough playback
6242 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306243 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306244 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306245 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306246 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006247 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306248 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306249 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306250 check_and_set_gapless_mode(adev, false);
6251 } else
6252 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006253
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306254 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006255 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6256 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306257 if (config->format == AUDIO_FORMAT_DSD) {
6258 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6259 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6260 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006261
6262 create_offload_callback_thread(out);
6263
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006264 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006265 switch (config->sample_rate) {
6266 case 0:
6267 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6268 break;
6269 case 8000:
6270 case 16000:
6271 case 48000:
6272 out->sample_rate = config->sample_rate;
6273 break;
6274 default:
6275 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
6276 config->sample_rate);
6277 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6278 ret = -EINVAL;
6279 goto error_open;
6280 }
6281 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6282 switch (config->channel_mask) {
6283 case AUDIO_CHANNEL_NONE:
6284 case AUDIO_CHANNEL_OUT_STEREO:
6285 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6286 break;
6287 default:
6288 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
6289 config->channel_mask);
6290 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6291 ret = -EINVAL;
6292 goto error_open;
6293 }
6294 switch (config->format) {
6295 case AUDIO_FORMAT_DEFAULT:
6296 case AUDIO_FORMAT_PCM_16_BIT:
6297 out->format = AUDIO_FORMAT_PCM_16_BIT;
6298 break;
6299 default:
6300 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
6301 config->format);
6302 config->format = AUDIO_FORMAT_PCM_16_BIT;
6303 ret = -EINVAL;
6304 goto error_open;
6305 }
6306
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306307 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006308 if (ret != 0) {
6309 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006310 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006311 goto error_open;
6312 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006313 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006314 if (config->sample_rate == 0)
6315 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6316 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6317 config->sample_rate != 8000) {
6318 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6319 ret = -EINVAL;
6320 goto error_open;
6321 }
6322 out->sample_rate = config->sample_rate;
6323 out->config.rate = config->sample_rate;
6324 if (config->format == AUDIO_FORMAT_DEFAULT)
6325 config->format = AUDIO_FORMAT_PCM_16_BIT;
6326 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6327 config->format = AUDIO_FORMAT_PCM_16_BIT;
6328 ret = -EINVAL;
6329 goto error_open;
6330 }
6331 out->format = config->format;
6332 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
6333 out->config = pcm_config_afe_proxy_playback;
6334 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006335 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05306336 unsigned int channels = 0;
6337 /*Update config params to default if not set by the caller*/
6338 if (config->sample_rate == 0)
6339 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6340 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6341 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6342 if (config->format == AUDIO_FORMAT_DEFAULT)
6343 config->format = AUDIO_FORMAT_PCM_16_BIT;
6344
6345 channels = audio_channel_count_from_out_mask(out->channel_mask);
6346
Varun Balaraje49253e2017-07-06 19:48:56 +05306347 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6348 out->usecase = get_interactive_usecase(adev);
6349 out->config = pcm_config_low_latency;
6350 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306351 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006352 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6353 out->flags);
6354 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006355 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6356 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6357 out->config = pcm_config_mmap_playback;
6358 out->stream.start = out_start;
6359 out->stream.stop = out_stop;
6360 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6361 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306362 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6363 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006364 out->hal_output_suspend_supported =
6365 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6366 out->dynamic_pm_qos_config_supported =
6367 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6368 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006369 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6370 } else {
6371 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6372 //the mixer path will be a string similar to "low-latency-playback resume"
6373 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6374 strlcat(out->pm_qos_mixer_path,
6375 " resume", MAX_MIXER_PATH_LEN);
6376 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6377 out->pm_qos_mixer_path);
6378 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306379 out->config = pcm_config_low_latency;
6380 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6381 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6382 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306383 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6384 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6385 if (out->config.period_size <= 0) {
6386 ALOGE("Invalid configuration period size is not valid");
6387 ret = -EINVAL;
6388 goto error_open;
6389 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306390 } else {
6391 /* primary path is the default path selected if no other outputs are available/suitable */
6392 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6393 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6394 }
6395 out->hal_ip_format = format = out->format;
6396 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6397 out->hal_op_format = pcm_format_to_hal(out->config.format);
6398 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6399 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006400 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306401 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306402 if (out->hal_ip_format != out->hal_op_format) {
6403 uint32_t buffer_size = out->config.period_size *
6404 format_to_bitwidth_table[out->hal_op_format] *
6405 out->config.channels;
6406 out->convert_buffer = calloc(1, buffer_size);
6407 if (out->convert_buffer == NULL){
6408 ALOGE("Allocation failed for convert buffer for size %d",
6409 out->compr_config.fragment_size);
6410 ret = -ENOMEM;
6411 goto error_open;
6412 }
6413 ALOGD("Convert buffer allocated of size %d", buffer_size);
6414 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006415 }
6416
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006417 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6418 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306419
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006420 /* TODO remove this hardcoding and check why width is zero*/
6421 if (out->bit_width == 0)
6422 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306423 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006424 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006425 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306426 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306427 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006428 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6429 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6430 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006431 if(adev->primary_output == NULL)
6432 adev->primary_output = out;
6433 else {
6434 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006435 ret = -EEXIST;
6436 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006437 }
6438 }
6439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006440 /* Check if this usecase is already existing */
6441 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006442 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6443 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006444 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006445 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006446 ret = -EEXIST;
6447 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006448 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006450 pthread_mutex_unlock(&adev->lock);
6451
6452 out->stream.common.get_sample_rate = out_get_sample_rate;
6453 out->stream.common.set_sample_rate = out_set_sample_rate;
6454 out->stream.common.get_buffer_size = out_get_buffer_size;
6455 out->stream.common.get_channels = out_get_channels;
6456 out->stream.common.get_format = out_get_format;
6457 out->stream.common.set_format = out_set_format;
6458 out->stream.common.standby = out_standby;
6459 out->stream.common.dump = out_dump;
6460 out->stream.common.set_parameters = out_set_parameters;
6461 out->stream.common.get_parameters = out_get_parameters;
6462 out->stream.common.add_audio_effect = out_add_audio_effect;
6463 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6464 out->stream.get_latency = out_get_latency;
6465 out->stream.set_volume = out_set_volume;
6466 out->stream.write = out_write;
6467 out->stream.get_render_position = out_get_render_position;
6468 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006469 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006470
Haynes Mathew George16081042017-05-31 17:16:49 -07006471 if (out->realtime)
6472 out->af_period_multiplier = af_period_multiplier;
6473 else
6474 out->af_period_multiplier = 1;
6475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006476 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006477 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006478 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006479
6480 config->format = out->stream.common.get_format(&out->stream.common);
6481 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6482 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05306483 register_format(out->format, out->supported_formats);
6484 register_channel_mask(out->channel_mask, out->supported_channel_masks);
6485 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006486
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306487 /*
6488 By locking output stream before registering, we allow the callback
6489 to update stream's state only after stream's initial state is set to
6490 adev state.
6491 */
6492 lock_output_stream(out);
6493 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6494 pthread_mutex_lock(&adev->lock);
6495 out->card_status = adev->card_status;
6496 pthread_mutex_unlock(&adev->lock);
6497 pthread_mutex_unlock(&out->lock);
6498
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006499 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306500 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006501 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006502
6503 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6504 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6505 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006506 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306507 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006508 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006509 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306510 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006511 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6512 out->usecase, PCM_PLAYBACK);
6513 hdlr_stream_cfg.flags = out->flags;
6514 hdlr_stream_cfg.type = PCM_PLAYBACK;
6515 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6516 &hdlr_stream_cfg);
6517 if (ret) {
6518 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6519 out->adsp_hdlr_stream_handle = NULL;
6520 }
6521 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306522 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006523 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006524 if (ret < 0) {
6525 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6526 out->ip_hdlr_handle = NULL;
6527 }
6528 }
Eric Laurent994a6932013-07-17 11:51:42 -07006529 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006530 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006531
6532error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306533 if (out->convert_buffer)
6534 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006535 free(out);
6536 *stream_out = NULL;
6537 ALOGD("%s: exit: ret %d", __func__, ret);
6538 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006539}
6540
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306541void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006542 struct audio_stream_out *stream)
6543{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006544 struct stream_out *out = (struct stream_out *)stream;
6545 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006546 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006547
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006548 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306549
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306550 // must deregister from sndmonitor first to prevent races
6551 // between the callback and close_stream
6552 audio_extn_snd_mon_unregister_listener(out);
6553
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006554 /* close adsp hdrl session before standby */
6555 if (out->adsp_hdlr_stream_handle) {
6556 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6557 if (ret)
6558 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6559 out->adsp_hdlr_stream_handle = NULL;
6560 }
6561
Manish Dewangan21a850a2017-08-14 12:03:55 +05306562 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006563 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6564 out->ip_hdlr_handle = NULL;
6565 }
6566
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006567 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306568 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006569 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306570 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306571 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006572 if(ret != 0)
6573 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6574 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006575 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006576 out_standby(&stream->common);
6577
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006578 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006579 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006580 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006581 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006582 if (out->compr_config.codec != NULL)
6583 free(out->compr_config.codec);
6584 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006585
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306586 out->a2dp_compress_mute = false;
6587
Varun Balaraje49253e2017-07-06 19:48:56 +05306588 if (is_interactive_usecase(out->usecase))
6589 free_interactive_usecase(adev, out->usecase);
6590
Ashish Jain83a6cc22016-06-28 14:34:17 +05306591 if (out->convert_buffer != NULL) {
6592 free(out->convert_buffer);
6593 out->convert_buffer = NULL;
6594 }
6595
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006596 if (adev->voice_tx_output == out)
6597 adev->voice_tx_output = NULL;
6598
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306599 if (adev->primary_output == out)
6600 adev->primary_output = NULL;
6601
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006602 pthread_cond_destroy(&out->cond);
6603 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006604 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006605 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006606}
6607
6608static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6609{
6610 struct audio_device *adev = (struct audio_device *)dev;
6611 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006612 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006613 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006614 int ret;
6615 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006616
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006617 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006618 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006619
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306620 if (!parms)
6621 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306622
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306623 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6624 if (ret >= 0) {
6625 /* When set to false, HAL should disable EC and NS */
6626 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6627 adev->bt_sco_on = true;
6628 else
6629 adev->bt_sco_on = false;
6630 }
6631
Naresh Tanniru4c630392014-05-12 01:05:52 +05306632 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006633 status = voice_set_parameters(adev, parms);
6634 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006635 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006636
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006637 status = platform_set_parameters(adev->platform, parms);
6638 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006639 goto done;
6640
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006641 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6642 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006643 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006644 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6645 adev->bluetooth_nrec = true;
6646 else
6647 adev->bluetooth_nrec = false;
6648 }
6649
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006650 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6651 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006652 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6653 adev->screen_off = false;
6654 else
6655 adev->screen_off = true;
6656 }
6657
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006658 ret = str_parms_get_int(parms, "rotation", &val);
6659 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006660 bool reverse_speakers = false;
6661 switch(val) {
6662 // FIXME: note that the code below assumes that the speakers are in the correct placement
6663 // relative to the user when the device is rotated 90deg from its default rotation. This
6664 // assumption is device-specific, not platform-specific like this code.
6665 case 270:
6666 reverse_speakers = true;
6667 break;
6668 case 0:
6669 case 90:
6670 case 180:
6671 break;
6672 default:
6673 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006674 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006675 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006676 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006677 // check and set swap
6678 // - check if orientation changed and speaker active
6679 // - set rotation and cache the rotation value
6680 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006681 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006682 }
6683
Mingming Yin514a8bc2014-07-29 15:22:21 -07006684 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6685 if (ret >= 0) {
6686 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6687 adev->bt_wb_speech_enabled = true;
6688 else
6689 adev->bt_wb_speech_enabled = false;
6690 }
6691
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006692 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6693 if (ret >= 0) {
6694 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306695 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08006696 if (audio_is_output_device(val) &&
6697 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006698 ALOGV("cache new ext disp type and edid");
6699 ret = platform_get_ext_disp_type(adev->platform);
6700 if (ret < 0) {
6701 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05306702 } else {
6703 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006704 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306705 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07006706 /*
6707 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6708 * Per AudioPolicyManager, USB device is higher priority than WFD.
6709 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6710 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6711 * starting voice call on USB
6712 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006713 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306714 if (ret >= 0)
6715 audio_extn_usb_add_device(device, atoi(value));
6716
Zhou Song6f862822017-11-06 17:27:57 +08006717 if (!audio_extn_usb_is_tunnel_supported()) {
6718 ALOGV("detected USB connect .. disable proxy");
6719 adev->allow_afe_proxy_usage = false;
6720 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006721 }
6722 }
6723
6724 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6725 if (ret >= 0) {
6726 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306727 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07006728 /*
6729 * The HDMI / Displayport disconnect handling has been moved to
6730 * audio extension to ensure that its parameters are not
6731 * invalidated prior to updating sysfs of the disconnect event
6732 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6733 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306734 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006735 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306736 if (ret >= 0)
6737 audio_extn_usb_remove_device(device, atoi(value));
6738
Zhou Song6f862822017-11-06 17:27:57 +08006739 if (!audio_extn_usb_is_tunnel_supported()) {
6740 ALOGV("detected USB disconnect .. enable proxy");
6741 adev->allow_afe_proxy_usage = true;
6742 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006743 }
6744 }
6745
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306746 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6747 if (ret >= 0) {
6748 struct audio_usecase *usecase;
6749 struct listnode *node;
6750 list_for_each(node, &adev->usecase_list) {
6751 usecase = node_to_item(node, struct audio_usecase, list);
6752 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07006753 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306754 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08006755
6756 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306757 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08006758 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306759 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306760 //force device switch to re configure encoder
6761 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306762 audio_extn_a2dp_set_handoff_mode(false);
6763 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306764 break;
6765 }
6766 }
6767 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006768
6769 //handle vr audio setparam
6770 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6771 value, sizeof(value));
6772 if (ret >= 0) {
6773 ALOGI("Setting vr mode to be %s", value);
6774 if (!strncmp(value, "true", 4)) {
6775 adev->vr_audio_mode_enabled = true;
6776 ALOGI("Setting vr mode to true");
6777 } else if (!strncmp(value, "false", 5)) {
6778 adev->vr_audio_mode_enabled = false;
6779 ALOGI("Setting vr mode to false");
6780 } else {
6781 ALOGI("wrong vr mode set");
6782 }
6783 }
6784
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306785 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006786done:
6787 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006788 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306789error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006790 ALOGV("%s: exit with code(%d)", __func__, status);
6791 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006792}
6793
6794static char* adev_get_parameters(const struct audio_hw_device *dev,
6795 const char *keys)
6796{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006797 struct audio_device *adev = (struct audio_device *)dev;
6798 struct str_parms *reply = str_parms_create();
6799 struct str_parms *query = str_parms_create_str(keys);
6800 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05306801 char value[256] = {0};
6802 int ret = 0;
6803
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006804 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006805 if (reply) {
6806 str_parms_destroy(reply);
6807 }
6808 if (query) {
6809 str_parms_destroy(query);
6810 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006811 ALOGE("adev_get_parameters: failed to create query or reply");
6812 return NULL;
6813 }
6814
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006815 //handle vr audio getparam
6816
6817 ret = str_parms_get_str(query,
6818 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6819 value, sizeof(value));
6820
6821 if (ret >= 0) {
6822 bool vr_audio_enabled = false;
6823 pthread_mutex_lock(&adev->lock);
6824 vr_audio_enabled = adev->vr_audio_mode_enabled;
6825 pthread_mutex_unlock(&adev->lock);
6826
6827 ALOGI("getting vr mode to %d", vr_audio_enabled);
6828
6829 if (vr_audio_enabled) {
6830 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6831 "true");
6832 goto exit;
6833 } else {
6834 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6835 "false");
6836 goto exit;
6837 }
6838 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006839
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006840 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006841 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08006842 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006843 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05306844 pthread_mutex_unlock(&adev->lock);
6845
Naresh Tannirud7205b62014-06-20 02:54:48 +05306846exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006847 str = str_parms_to_str(reply);
6848 str_parms_destroy(query);
6849 str_parms_destroy(reply);
6850
6851 ALOGV("%s: exit: returns - %s", __func__, str);
6852 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006853}
6854
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006855static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006856{
6857 return 0;
6858}
6859
6860static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
6861{
Haynes Mathew George5191a852013-09-11 14:19:36 -07006862 int ret;
6863 struct audio_device *adev = (struct audio_device *)dev;
6864 pthread_mutex_lock(&adev->lock);
6865 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07006866 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07006867 pthread_mutex_unlock(&adev->lock);
6868 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006869}
6870
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006871static int adev_set_master_volume(struct audio_hw_device *dev __unused,
6872 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006873{
6874 return -ENOSYS;
6875}
6876
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006877static int adev_get_master_volume(struct audio_hw_device *dev __unused,
6878 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006879{
6880 return -ENOSYS;
6881}
6882
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006883static int adev_set_master_mute(struct audio_hw_device *dev __unused,
6884 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006885{
6886 return -ENOSYS;
6887}
6888
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006889static int adev_get_master_mute(struct audio_hw_device *dev __unused,
6890 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006891{
6892 return -ENOSYS;
6893}
6894
6895static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
6896{
6897 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07006898 struct listnode *node;
6899 struct audio_usecase *usecase = NULL;
6900 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006901 pthread_mutex_lock(&adev->lock);
6902 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006903 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006904 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08006905 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07006906 list_for_each(node, &adev->usecase_list) {
6907 usecase = node_to_item(node, struct audio_usecase, list);
6908 if (usecase->type == VOICE_CALL)
6909 break;
6910 }
6911 if (usecase &&
6912 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
6913 ret = audio_extn_usb_check_and_set_svc_int(usecase,
6914 true);
6915 if (ret != 0) {
6916 /* default service interval was successfully updated,
6917 reopen USB backend with new service interval */
6918 check_usecases_codec_backend(adev,
6919 usecase,
6920 usecase->out_snd_device);
6921 }
6922 }
6923
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006924 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07006925 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006926 adev->current_call_output = NULL;
6927 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006928 }
6929 pthread_mutex_unlock(&adev->lock);
6930 return 0;
6931}
6932
6933static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
6934{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006935 int ret;
6936
6937 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08006938 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006939 ret = voice_set_mic_mute((struct audio_device *)dev, state);
6940 pthread_mutex_unlock(&adev->lock);
6941
6942 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006943}
6944
6945static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
6946{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006947 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006948 return 0;
6949}
6950
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006951static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006952 const struct audio_config *config)
6953{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006954 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006955
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006956 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
6957 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006958}
6959
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006960static bool adev_input_allow_hifi_record(struct audio_device *adev,
6961 audio_devices_t devices,
6962 audio_input_flags_t flags,
6963 audio_source_t source) {
6964 const bool allowed = true;
6965
6966 if (!audio_is_usb_in_device(devices))
6967 return !allowed;
6968
6969 switch (flags) {
6970 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006971 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07006972 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
6973 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006974 default:
6975 return !allowed;
6976 }
6977
6978 switch (source) {
6979 case AUDIO_SOURCE_DEFAULT:
6980 case AUDIO_SOURCE_MIC:
6981 case AUDIO_SOURCE_UNPROCESSED:
6982 break;
6983 default:
6984 return !allowed;
6985 }
6986
6987 switch (adev->mode) {
6988 case 0:
6989 break;
6990 default:
6991 return !allowed;
6992 }
6993
6994 return allowed;
6995}
6996
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006997static int adev_update_voice_comm_input_stream(struct stream_in *in,
6998 struct audio_config *config)
6999{
7000 bool valid_rate = (config->sample_rate == 8000 ||
7001 config->sample_rate == 16000 ||
7002 config->sample_rate == 32000 ||
7003 config->sample_rate == 48000);
7004 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
7005
7006#ifndef COMPRESS_VOIP_ENABLED
kunleizd96526c2018-04-09 11:12:32 +08007007 if (valid_rate && valid_ch &&
7008 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007009 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7010 in->config = default_pcm_config_voip_copp;
7011 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
7012 DEFAULT_VOIP_BUF_DURATION_MS,
7013 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
7014 } else {
kunleizbdd9ad02018-04-24 10:53:17 +08007015 ALOGW("%s No valid input in voip, use defaults"
7016 "sample rate %u, channel mask 0x%X",
7017 __func__, config->sample_rate, in->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007018 }
7019 in->config.rate = config->sample_rate;
7020 in->sample_rate = config->sample_rate;
7021#else
7022 //XXX needed for voice_extn_compress_voip_open_input_stream
7023 in->config.rate = config->sample_rate;
7024 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7025 voice_extn_compress_voip_is_active(in->dev)) &&
7026 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7027 valid_rate && valid_ch) {
7028 voice_extn_compress_voip_open_input_stream(in);
7029 // update rate entries to match config from AF
7030 in->config.rate = config->sample_rate;
7031 in->sample_rate = config->sample_rate;
7032 } else {
7033 ALOGW("%s compress voip not active, use defaults", __func__);
7034 }
7035#endif
7036 return 0;
7037}
7038
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007039static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007040 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007041 audio_devices_t devices,
7042 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007043 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307044 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007045 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007046 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007047{
7048 struct audio_device *adev = (struct audio_device *)dev;
7049 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007050 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007051 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007052 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05307053 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007054 bool is_usb_dev = audio_is_usb_in_device(devices);
7055 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
7056 devices,
7057 flags,
7058 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307059
kunleizdff872d2018-08-20 14:40:33 +08007060 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007061 is_usb_dev = false;
7062 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
7063 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
7064 __func__, devices);
7065 }
7066
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007067 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007068
7069 if (!(is_usb_dev && may_use_hifi_record)) {
7070 if (config->sample_rate == 0)
7071 config->sample_rate = 48000;
7072 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7073 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7074 if (config->format == AUDIO_FORMAT_DEFAULT)
7075 config->format = AUDIO_FORMAT_PCM_16_BIT;
7076
7077 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
7078
7079 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
7080 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05307081 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007082
7083 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007084
7085 if (!in) {
7086 ALOGE("failed to allocate input stream");
7087 return -ENOMEM;
7088 }
7089
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307090 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307091 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7092 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007093 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007094 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007096 in->stream.common.get_sample_rate = in_get_sample_rate;
7097 in->stream.common.set_sample_rate = in_set_sample_rate;
7098 in->stream.common.get_buffer_size = in_get_buffer_size;
7099 in->stream.common.get_channels = in_get_channels;
7100 in->stream.common.get_format = in_get_format;
7101 in->stream.common.set_format = in_set_format;
7102 in->stream.common.standby = in_standby;
7103 in->stream.common.dump = in_dump;
7104 in->stream.common.set_parameters = in_set_parameters;
7105 in->stream.common.get_parameters = in_get_parameters;
7106 in->stream.common.add_audio_effect = in_add_audio_effect;
7107 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7108 in->stream.set_gain = in_set_gain;
7109 in->stream.read = in_read;
7110 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307111 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007112
7113 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007114 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007115 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007116 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007117 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007118 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007119 in->bit_width = 16;
7120 in->af_period_multiplier = 1;
7121
7122 /* Update config params with the requested sample rate and channels */
7123 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
7124 (adev->mode != AUDIO_MODE_IN_CALL)) {
7125 ret = -EINVAL;
7126 goto err_open;
7127 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007128
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007129 if (is_usb_dev && may_use_hifi_record) {
7130 /* HiFi record selects an appropriate format, channel, rate combo
7131 depending on sink capabilities*/
7132 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7133 &config->format,
7134 &in->supported_formats[0],
7135 MAX_SUPPORTED_FORMATS,
7136 &config->channel_mask,
7137 &in->supported_channel_masks[0],
7138 MAX_SUPPORTED_CHANNEL_MASKS,
7139 &config->sample_rate,
7140 &in->supported_sample_rates[0],
7141 MAX_SUPPORTED_SAMPLE_RATES);
7142 if (ret != 0) {
7143 ret = -EINVAL;
7144 goto err_open;
7145 }
7146 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007147 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307148 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05307149 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
7150 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
7151 in->config.format = PCM_FORMAT_S32_LE;
7152 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307153 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
7154 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
7155 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
7156 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7157 bool ret_error = false;
7158 in->bit_width = 24;
7159 /* 24 bit is restricted to UNPROCESSED source only,also format supported
7160 from HAL is 24_packed and 8_24
7161 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
7162 24_packed return error indicating supported format is 24_packed
7163 *> In case of any other source requesting 24 bit or float return error
7164 indicating format supported is 16 bit only.
7165
7166 on error flinger will retry with supported format passed
7167 */
7168 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
7169 (source != AUDIO_SOURCE_CAMCORDER)) {
7170 config->format = AUDIO_FORMAT_PCM_16_BIT;
7171 if (config->sample_rate > 48000)
7172 config->sample_rate = 48000;
7173 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07007174 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
7175 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307176 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
7177 ret_error = true;
7178 }
7179
7180 if (ret_error) {
7181 ret = -EINVAL;
7182 goto err_open;
7183 }
7184 }
7185
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007186 in->channel_mask = config->channel_mask;
7187 in->format = config->format;
7188
7189 in->usecase = USECASE_AUDIO_RECORD;
7190 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
7191 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
7192 is_low_latency = true;
7193#if LOW_LATENCY_CAPTURE_USE_CASE
7194 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
7195#endif
7196 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
7197 }
7198
7199 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
7200 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
7201 in->realtime = 0;
7202 in->usecase = USECASE_AUDIO_RECORD_MMAP;
7203 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07007204 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007205 in->stream.start = in_start;
7206 in->stream.stop = in_stop;
7207 in->stream.create_mmap_buffer = in_create_mmap_buffer;
7208 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007209 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007210 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
7211 } else if (in->realtime) {
7212 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07007213 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007214 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007215 in->sample_rate = in->config.rate;
7216 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07007217 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007218 in->usecase = USECASE_AUDIO_RECORD_HIFI;
7219 in->config = pcm_config_audio_capture;
7220 frame_size = audio_stream_in_frame_size(&in->stream);
7221 buffer_size = get_input_buffer_size(config->sample_rate,
7222 config->format,
7223 channel_count,
7224 false /*is_low_latency*/);
7225 in->config.period_size = buffer_size / frame_size;
7226 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007227 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07007228 switch (config->format) {
7229 case AUDIO_FORMAT_PCM_32_BIT:
7230 in->bit_width = 32;
7231 break;
7232 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
7233 case AUDIO_FORMAT_PCM_8_24_BIT:
7234 in->bit_width = 24;
7235 break;
7236 default:
7237 in->bit_width = 16;
7238 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007239 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007240 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007241 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05307242 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007243 if (config->sample_rate == 0)
7244 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7245 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
7246 config->sample_rate != 8000) {
7247 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7248 ret = -EINVAL;
7249 goto err_open;
7250 }
7251 if (config->format == AUDIO_FORMAT_DEFAULT)
7252 config->format = AUDIO_FORMAT_PCM_16_BIT;
7253 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
7254 config->format = AUDIO_FORMAT_PCM_16_BIT;
7255 ret = -EINVAL;
7256 goto err_open;
7257 }
7258
7259 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
7260 in->config = pcm_config_afe_proxy_record;
7261 in->config.channels = channel_count;
7262 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307263 in->sample_rate = config->sample_rate;
Haynes Mathew George46740472017-10-27 18:40:12 -07007264 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05307265 int ret_val;
7266 pthread_mutex_lock(&adev->lock);
7267 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
7268 in, config, &channel_mask_updated);
7269 pthread_mutex_unlock(&adev->lock);
7270
7271 if (!ret_val) {
7272 if (channel_mask_updated == true) {
7273 ALOGD("%s: return error to retry with updated channel mask (%#x)",
7274 __func__, config->channel_mask);
7275 ret = -EINVAL;
7276 goto err_open;
7277 }
7278 ALOGD("%s: created multi-channel session succesfully",__func__);
7279 } else if (audio_extn_compr_cap_enabled() &&
7280 audio_extn_compr_cap_format_supported(config->format) &&
7281 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
7282 audio_extn_compr_cap_init(in);
7283 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05307284 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05307285 ret = audio_extn_cin_configure_input_stream(in);
7286 if (ret)
7287 goto err_open;
7288 } else {
7289 in->config = pcm_config_audio_capture;
7290 in->config.rate = config->sample_rate;
7291 in->config.format = pcm_format_from_audio_format(config->format);
7292 in->config.channels = channel_count;
7293 in->sample_rate = config->sample_rate;
7294 in->format = config->format;
7295 frame_size = audio_stream_in_frame_size(&in->stream);
7296 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07007297 config->format,
7298 channel_count,
7299 is_low_latency);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307300 in->config.period_size = buffer_size / frame_size;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007301
Revathi Uddarajud2634032017-12-07 14:42:34 +05307302 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
7303 /* optionally use VOIP usecase depending on config(s) */
7304 ret = adev_update_voice_comm_input_stream(in, config);
7305 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007306
Revathi Uddarajud2634032017-12-07 14:42:34 +05307307 if (ret) {
7308 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
7309 goto err_open;
7310 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007311 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007312 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307313 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7314 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007315 devices, flags, in->format,
7316 in->sample_rate, in->bit_width,
7317 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307318 register_format(in->format, in->supported_formats);
7319 register_channel_mask(in->channel_mask, in->supported_channel_masks);
7320 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307321
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007322 /* This stream could be for sound trigger lab,
7323 get sound trigger pcm if present */
7324 audio_extn_sound_trigger_check_and_get_session(in);
7325
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307326 lock_input_stream(in);
7327 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
7328 pthread_mutex_lock(&adev->lock);
7329 in->card_status = adev->card_status;
7330 pthread_mutex_unlock(&adev->lock);
7331 pthread_mutex_unlock(&in->lock);
7332
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007333 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07007334 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007335 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007336
7337err_open:
7338 free(in);
7339 *stream_in = NULL;
7340 return ret;
7341}
7342
7343static void adev_close_input_stream(struct audio_hw_device *dev,
7344 struct audio_stream_in *stream)
7345{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007346 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007347 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007348 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307349
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307350 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007351
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307352 // must deregister from sndmonitor first to prevent races
7353 // between the callback and close_stream
7354 audio_extn_snd_mon_unregister_listener(stream);
7355
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307356 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07007357 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307358
Pallavid7c7a272018-01-16 11:22:55 +05307359 if (in == NULL) {
7360 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
7361 return;
7362 }
7363
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007364 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307365 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007366 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307367 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007368 if (ret != 0)
7369 ALOGE("%s: Compress voip input cannot be closed, error:%d",
7370 __func__, ret);
7371 } else
7372 in_standby(&stream->common);
7373
Revathi Uddarajud2634032017-12-07 14:42:34 +05307374 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07007375 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007376 audio_extn_ssr_deinit();
7377 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007378
Garmond Leunge2433c32017-09-28 21:51:22 -07007379 if (audio_extn_ffv_get_stream() == in) {
7380 audio_extn_ffv_stream_deinit();
7381 }
7382
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307383 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07007384 audio_extn_compr_cap_format_supported(in->config.format))
7385 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05307386
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307387 if (audio_extn_cin_attached_usecase(in->usecase))
7388 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007389
Mingming Yinfd7607b2016-01-22 12:48:44 -08007390 if (in->is_st_session) {
7391 ALOGV("%s: sound trigger pcm stop lab", __func__);
7392 audio_extn_sound_trigger_stop_lab(in);
7393 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007394 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307395 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007396 return;
7397}
7398
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307399int adev_create_audio_patch(struct audio_hw_device *dev,
7400 unsigned int num_sources,
7401 const struct audio_port_config *sources,
7402 unsigned int num_sinks,
7403 const struct audio_port_config *sinks,
7404 audio_patch_handle_t *handle)
7405{
7406
7407
7408 return audio_extn_hw_loopback_create_audio_patch(dev,
7409 num_sources,
7410 sources,
7411 num_sinks,
7412 sinks,
7413 handle);
7414
7415}
7416
7417int adev_release_audio_patch(struct audio_hw_device *dev,
7418 audio_patch_handle_t handle)
7419{
7420 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
7421}
7422
7423int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
7424{
7425 return audio_extn_hw_loopback_get_audio_port(dev, config);
7426}
7427
7428int adev_set_audio_port_config(struct audio_hw_device *dev,
7429 const struct audio_port_config *config)
7430{
7431 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
7432}
7433
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007434static int adev_dump(const audio_hw_device_t *device __unused,
7435 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007436{
7437 return 0;
7438}
7439
7440static int adev_close(hw_device_t *device)
7441{
7442 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07007443
7444 if (!adev)
7445 return 0;
7446
7447 pthread_mutex_lock(&adev_init_lock);
7448
7449 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307450 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007451 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08007452 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307453 audio_extn_utils_release_streams_cfg_lists(
7454 &adev->streams_output_cfg_list,
7455 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307456 if (audio_extn_qaf_is_enabled())
7457 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007458 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007459 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007460 free(adev->snd_dev_ref_cnt);
7461 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007462 if (adev->adm_deinit)
7463 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307464 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007465 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307466 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307467 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007468 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307469 if (adev->device_cfg_params) {
7470 free(adev->device_cfg_params);
7471 adev->device_cfg_params = NULL;
7472 }
Kiran Kandi910e1862013-10-29 13:29:42 -07007473 free(device);
7474 adev = NULL;
7475 }
7476 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007477
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007478 return 0;
7479}
7480
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007481/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
7482 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
7483 * just that it _might_ work.
7484 */
7485static int period_size_is_plausible_for_low_latency(int period_size)
7486{
7487 switch (period_size) {
7488 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07007489 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007490 case 240:
7491 case 320:
7492 case 480:
7493 return 1;
7494 default:
7495 return 0;
7496 }
7497}
7498
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307499static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
7500{
7501 bool is_snd_card_status = false;
7502 bool is_ext_device_status = false;
7503 char value[32];
7504 int card = -1;
7505 card_status_t status;
7506
7507 if (cookie != adev || !parms)
7508 return;
7509
7510 if (!parse_snd_card_status(parms, &card, &status)) {
7511 is_snd_card_status = true;
7512 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
7513 is_ext_device_status = true;
7514 } else {
7515 // not a valid event
7516 return;
7517 }
7518
7519 pthread_mutex_lock(&adev->lock);
7520 if (card == adev->snd_card || is_ext_device_status) {
7521 if (is_snd_card_status && adev->card_status != status) {
7522 adev->card_status = status;
7523 platform_snd_card_update(adev->platform, status);
7524 audio_extn_fm_set_parameters(adev, parms);
7525 } else if (is_ext_device_status) {
7526 platform_set_parameters(adev->platform, parms);
7527 }
7528 }
7529 pthread_mutex_unlock(&adev->lock);
7530 return;
7531}
7532
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307533/* out and adev lock held */
7534static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
7535{
7536 struct audio_usecase *uc_info;
7537 float left_p;
7538 float right_p;
7539 audio_devices_t devices;
7540
7541 uc_info = get_usecase_from_list(adev, out->usecase);
7542 if (uc_info == NULL) {
7543 ALOGE("%s: Could not find the usecase (%d) in the list",
7544 __func__, out->usecase);
7545 return -EINVAL;
7546 }
7547
7548 ALOGD("%s: enter: usecase(%d: %s)", __func__,
7549 out->usecase, use_case_table[out->usecase]);
7550
7551 if (restore) {
7552 // restore A2DP device for active usecases and unmute if required
7553 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
7554 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
7555 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
7556 select_devices(adev, uc_info->id);
7557 pthread_mutex_lock(&out->compr_mute_lock);
7558 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7559 (out->a2dp_compress_mute)) {
7560 out->a2dp_compress_mute = false;
7561 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
7562 }
7563 pthread_mutex_unlock(&out->compr_mute_lock);
7564 }
7565 } else {
7566 // mute compress stream if suspended
7567 pthread_mutex_lock(&out->compr_mute_lock);
7568 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7569 (!out->a2dp_compress_mute)) {
7570 if (!out->standby) {
7571 ALOGD("%s: selecting speaker and muting stream", __func__);
7572 devices = out->devices;
7573 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
7574 left_p = out->volume_l;
7575 right_p = out->volume_r;
7576 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7577 compress_pause(out->compr);
7578 out_set_compr_volume(&out->stream, (float)0, (float)0);
7579 out->a2dp_compress_mute = true;
7580 select_devices(adev, out->usecase);
7581 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7582 compress_resume(out->compr);
7583 out->devices = devices;
7584 out->volume_l = left_p;
7585 out->volume_r = right_p;
7586 }
7587 }
7588 pthread_mutex_unlock(&out->compr_mute_lock);
7589 }
7590 ALOGV("%s: exit", __func__);
7591 return 0;
7592}
7593
7594int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
7595{
7596 int ret = 0;
7597
7598 lock_output_stream(out);
7599 pthread_mutex_lock(&adev->lock);
7600
7601 ret = check_a2dp_restore_l(adev, out, restore);
7602
7603 pthread_mutex_unlock(&adev->lock);
7604 pthread_mutex_unlock(&out->lock);
7605 return ret;
7606}
7607
Haynes Mathew George01156f92018-04-13 15:29:54 -07007608void adev_on_battery_status_changed(bool charging)
7609{
7610 pthread_mutex_lock(&adev->lock);
7611 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
7612 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08007613 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07007614 pthread_mutex_unlock(&adev->lock);
7615}
7616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007617static int adev_open(const hw_module_t *module, const char *name,
7618 hw_device_t **device)
7619{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307620 int ret;
7621
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007622 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007623 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
7624
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007625 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07007626 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007627 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07007628 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007629 ALOGD("%s: returning existing instance of adev", __func__);
7630 ALOGD("%s: exit", __func__);
7631 pthread_mutex_unlock(&adev_init_lock);
7632 return 0;
7633 }
7634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007635 adev = calloc(1, sizeof(struct audio_device));
7636
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007637 if (!adev) {
7638 pthread_mutex_unlock(&adev_init_lock);
7639 return -ENOMEM;
7640 }
7641
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007642 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
7643
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05307644#ifdef DYNAMIC_LOG_ENABLED
7645 register_for_dynamic_logging("hal");
7646#endif
7647
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007648 adev->device.common.tag = HARDWARE_DEVICE_TAG;
7649 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7650 adev->device.common.module = (struct hw_module_t *)module;
7651 adev->device.common.close = adev_close;
7652
7653 adev->device.init_check = adev_init_check;
7654 adev->device.set_voice_volume = adev_set_voice_volume;
7655 adev->device.set_master_volume = adev_set_master_volume;
7656 adev->device.get_master_volume = adev_get_master_volume;
7657 adev->device.set_master_mute = adev_set_master_mute;
7658 adev->device.get_master_mute = adev_get_master_mute;
7659 adev->device.set_mode = adev_set_mode;
7660 adev->device.set_mic_mute = adev_set_mic_mute;
7661 adev->device.get_mic_mute = adev_get_mic_mute;
7662 adev->device.set_parameters = adev_set_parameters;
7663 adev->device.get_parameters = adev_get_parameters;
7664 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
7665 adev->device.open_output_stream = adev_open_output_stream;
7666 adev->device.close_output_stream = adev_close_output_stream;
7667 adev->device.open_input_stream = adev_open_input_stream;
7668 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307669 adev->device.create_audio_patch = adev_create_audio_patch;
7670 adev->device.release_audio_patch = adev_release_audio_patch;
7671 adev->device.get_audio_port = adev_get_audio_port;
7672 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007673 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307674 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007675
7676 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007677 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08007678 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007679 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007680 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007681 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08007682 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07007683 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307684 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07007685 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07007686 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007687 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08007688 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08007689 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007690 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05307691 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307692 adev->perf_lock_opts[0] = 0x101;
7693 adev->perf_lock_opts[1] = 0x20E;
7694 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007695 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307696
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007697 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07007698 adev->platform = platform_init(adev);
7699 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007700 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007701 free(adev->snd_dev_ref_cnt);
7702 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007703 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07007704 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7705 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08007706 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007707 return -EINVAL;
7708 }
Eric Laurentc4aef752013-09-12 17:45:53 -07007709
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307710 if (audio_extn_qaf_is_enabled()) {
7711 ret = audio_extn_qaf_init(adev);
7712 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007713 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307714 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007715 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307716 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7717 *device = NULL;
7718 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307719 return ret;
7720 }
7721
7722 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
7723 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
7724 }
7725
Eric Laurentc4aef752013-09-12 17:45:53 -07007726 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
7727 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
7728 if (adev->visualizer_lib == NULL) {
7729 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
7730 } else {
7731 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
7732 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007733 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007734 "visualizer_hal_start_output");
7735 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007736 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007737 "visualizer_hal_stop_output");
7738 }
7739 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05307740 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08007741 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007742 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307743 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007744 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07007745
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007746 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
7747 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
7748 if (adev->offload_effects_lib == NULL) {
7749 ALOGE("%s: DLOPEN failed for %s", __func__,
7750 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7751 } else {
7752 ALOGV("%s: DLOPEN successful for %s", __func__,
7753 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7754 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05307755 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007756 "offload_effects_bundle_hal_start_output");
7757 adev->offload_effects_stop_output =
7758 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
7759 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007760 adev->offload_effects_set_hpx_state =
7761 (int (*)(bool))dlsym(adev->offload_effects_lib,
7762 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05307763 adev->offload_effects_get_parameters =
7764 (void (*)(struct str_parms *, struct str_parms *))
7765 dlsym(adev->offload_effects_lib,
7766 "offload_effects_bundle_get_parameters");
7767 adev->offload_effects_set_parameters =
7768 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
7769 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007770 }
7771 }
7772
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007773 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
7774 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
7775 if (adev->adm_lib == NULL) {
7776 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
7777 } else {
7778 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
7779 adev->adm_init = (adm_init_t)
7780 dlsym(adev->adm_lib, "adm_init");
7781 adev->adm_deinit = (adm_deinit_t)
7782 dlsym(adev->adm_lib, "adm_deinit");
7783 adev->adm_register_input_stream = (adm_register_input_stream_t)
7784 dlsym(adev->adm_lib, "adm_register_input_stream");
7785 adev->adm_register_output_stream = (adm_register_output_stream_t)
7786 dlsym(adev->adm_lib, "adm_register_output_stream");
7787 adev->adm_deregister_stream = (adm_deregister_stream_t)
7788 dlsym(adev->adm_lib, "adm_deregister_stream");
7789 adev->adm_request_focus = (adm_request_focus_t)
7790 dlsym(adev->adm_lib, "adm_request_focus");
7791 adev->adm_abandon_focus = (adm_abandon_focus_t)
7792 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007793 adev->adm_set_config = (adm_set_config_t)
7794 dlsym(adev->adm_lib, "adm_set_config");
7795 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
7796 dlsym(adev->adm_lib, "adm_request_focus_v2");
7797 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
7798 dlsym(adev->adm_lib, "adm_is_noirq_avail");
7799 adev->adm_on_routing_change = (adm_on_routing_change_t)
7800 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007801 }
7802 }
7803
Mingming Yin514a8bc2014-07-29 15:22:21 -07007804 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007805 //initialize this to false for now,
7806 //this will be set to true through set param
7807 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07007808
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07007809 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007810 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007811 adev->dsp_bit_width_enforce_mode =
7812 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007813
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307814 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
7815 &adev->streams_output_cfg_list,
7816 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007817
Kiran Kandi910e1862013-10-29 13:29:42 -07007818 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007819
7820 char value[PROPERTY_VALUE_MAX];
7821 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007822 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007823 trial = atoi(value);
7824 if (period_size_is_plausible_for_low_latency(trial)) {
7825 pcm_config_low_latency.period_size = trial;
7826 pcm_config_low_latency.start_threshold = trial / 4;
7827 pcm_config_low_latency.avail_min = trial / 4;
7828 configured_low_latency_capture_period_size = trial;
7829 }
7830 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007831 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007832 trial = atoi(value);
7833 if (period_size_is_plausible_for_low_latency(trial)) {
7834 configured_low_latency_capture_period_size = trial;
7835 }
7836 }
7837
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08007838 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
7839
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007840 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007841 af_period_multiplier = atoi(value);
7842 if (af_period_multiplier < 0)
7843 af_period_multiplier = 2;
7844 else if (af_period_multiplier > 4)
7845 af_period_multiplier = 4;
7846
7847 ALOGV("new period_multiplier = %d", af_period_multiplier);
7848 }
7849
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007850 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007851 pthread_mutex_unlock(&adev_init_lock);
7852
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007853 if (adev->adm_init)
7854 adev->adm_data = adev->adm_init();
7855
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307856 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307857 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007858 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307859
7860 audio_extn_snd_mon_init();
7861 pthread_mutex_lock(&adev->lock);
7862 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
7863 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07007864 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
7865 /*
7866 * if the battery state callback happens before charging can be queried,
7867 * it will be guarded with the adev->lock held in the cb function and so
7868 * the callback value will reflect the latest state
7869 */
7870 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307871 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08007872 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
7873 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307874 /* Allocate memory for Device config params */
7875 adev->device_cfg_params = (struct audio_device_config_param*)
7876 calloc(platform_get_max_codec_backend(),
7877 sizeof(struct audio_device_config_param));
7878 if (adev->device_cfg_params == NULL)
7879 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307880
Eric Laurent994a6932013-07-17 11:51:42 -07007881 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007882 return 0;
7883}
7884
7885static struct hw_module_methods_t hal_module_methods = {
7886 .open = adev_open,
7887};
7888
7889struct audio_module HAL_MODULE_INFO_SYM = {
7890 .common = {
7891 .tag = HARDWARE_MODULE_TAG,
7892 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
7893 .hal_api_version = HARDWARE_HAL_API_VERSION,
7894 .id = AUDIO_HARDWARE_MODULE_ID,
7895 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08007896 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007897 .methods = &hal_module_methods,
7898 },
7899};