blob: 30a77480647aab039905152fc73fd6f8f3010c01 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Dhanalakshmi Siddani0f1dfd52019-01-09 12:38:13 +05302 * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070066#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070068#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053077#include "ip_hdlr_intf.h"
Balázs Triszka6e101332018-02-26 22:11:10 +010078#include "ultrasound.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080081#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080082
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053083#ifdef DYNAMIC_LOG_ENABLED
84#include <log_xml_parser.h>
85#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
86#include <log_utils.h>
87#endif
88
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070089#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053090/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
91#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070092#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuriebe78a72018-10-04 18:23:46 -070093#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070094#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053095#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070096
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070097#define PROXY_OPEN_RETRY_COUNT 100
98#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080099
Mingming Yin08c7e312015-03-16 18:10:58 -0700100#ifdef USE_LL_AS_PRIMARY_OUTPUT
101#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
102#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
103#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800104#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700105#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
106#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800107
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700108#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700109#define DEFAULT_VOIP_BUF_DURATION_MS 20
110#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
111#define DEFAULT_VOIP_SAMP_RATE 48000
112
113#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
114
115struct pcm_config default_pcm_config_voip_copp = {
116 .channels = 1,
117 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
118 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
119 .period_count = 2,
120 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800121 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
122 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700123};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700124
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700125#define MIN_CHANNEL_COUNT 1
126#define DEFAULT_CHANNEL_COUNT 2
127#define MAX_HIFI_CHANNEL_COUNT 8
128
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700129static unsigned int configured_low_latency_capture_period_size =
130 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
131
Haynes Mathew George16081042017-05-31 17:16:49 -0700132#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
133#define MMAP_PERIOD_COUNT_MIN 32
134#define MMAP_PERIOD_COUNT_MAX 512
135#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
136
Eric Laurentb23d5282013-05-14 15:27:20 -0700137struct pcm_config pcm_config_deep_buffer = {
138 .channels = 2,
139 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
140 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
141 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
142 .format = PCM_FORMAT_S16_LE,
143 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
144 .stop_threshold = INT_MAX,
145 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
146};
147
148struct pcm_config pcm_config_low_latency = {
149 .channels = 2,
150 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
151 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
152 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
155 .stop_threshold = INT_MAX,
156 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
157};
158
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700159static int af_period_multiplier = 4;
160struct pcm_config pcm_config_rt = {
161 .channels = 2,
162 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
163 .period_size = ULL_PERIOD_SIZE, //1 ms
164 .period_count = 512, //=> buffer size is 512ms
165 .format = PCM_FORMAT_S16_LE,
166 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
167 .stop_threshold = INT_MAX,
168 .silence_threshold = 0,
169 .silence_size = 0,
170 .avail_min = ULL_PERIOD_SIZE, //1 ms
171};
172
Eric Laurentb23d5282013-05-14 15:27:20 -0700173struct pcm_config pcm_config_hdmi_multi = {
174 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
175 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
176 .period_size = HDMI_MULTI_PERIOD_SIZE,
177 .period_count = HDMI_MULTI_PERIOD_COUNT,
178 .format = PCM_FORMAT_S16_LE,
179 .start_threshold = 0,
180 .stop_threshold = INT_MAX,
181 .avail_min = 0,
182};
183
Haynes Mathew George16081042017-05-31 17:16:49 -0700184struct pcm_config pcm_config_mmap_playback = {
185 .channels = 2,
186 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
187 .period_size = MMAP_PERIOD_SIZE,
188 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
189 .format = PCM_FORMAT_S16_LE,
190 .start_threshold = MMAP_PERIOD_SIZE*8,
191 .stop_threshold = INT32_MAX,
192 .silence_threshold = 0,
193 .silence_size = 0,
194 .avail_min = MMAP_PERIOD_SIZE, //1 ms
195};
196
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700197struct pcm_config pcm_config_hifi = {
198 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
199 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
200 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
201 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
202 .format = PCM_FORMAT_S24_3LE,
203 .start_threshold = 0,
204 .stop_threshold = INT_MAX,
205 .avail_min = 0,
206};
207
Eric Laurentb23d5282013-05-14 15:27:20 -0700208struct pcm_config pcm_config_audio_capture = {
209 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700210 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
211 .format = PCM_FORMAT_S16_LE,
212};
213
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700214struct pcm_config pcm_config_audio_capture_rt = {
215 .channels = 2,
216 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
217 .period_size = ULL_PERIOD_SIZE,
218 .period_count = 512,
219 .format = PCM_FORMAT_S16_LE,
220 .start_threshold = 0,
221 .stop_threshold = INT_MAX,
222 .silence_threshold = 0,
223 .silence_size = 0,
224 .avail_min = ULL_PERIOD_SIZE, //1 ms
225};
226
Haynes Mathew George16081042017-05-31 17:16:49 -0700227struct pcm_config pcm_config_mmap_capture = {
228 .channels = 2,
229 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
230 .period_size = MMAP_PERIOD_SIZE,
231 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
232 .format = PCM_FORMAT_S16_LE,
233 .start_threshold = 0,
234 .stop_threshold = INT_MAX,
235 .silence_threshold = 0,
236 .silence_size = 0,
237 .avail_min = MMAP_PERIOD_SIZE, //1 ms
238};
239
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700240#define AFE_PROXY_CHANNEL_COUNT 2
241#define AFE_PROXY_SAMPLING_RATE 48000
242
243#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
244#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
245
246struct pcm_config pcm_config_afe_proxy_playback = {
247 .channels = AFE_PROXY_CHANNEL_COUNT,
248 .rate = AFE_PROXY_SAMPLING_RATE,
249 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
250 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
251 .format = PCM_FORMAT_S16_LE,
252 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
253 .stop_threshold = INT_MAX,
254 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
255};
256
257#define AFE_PROXY_RECORD_PERIOD_SIZE 768
258#define AFE_PROXY_RECORD_PERIOD_COUNT 4
259
260struct pcm_config pcm_config_afe_proxy_record = {
261 .channels = AFE_PROXY_CHANNEL_COUNT,
262 .rate = AFE_PROXY_SAMPLING_RATE,
263 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
264 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
265 .format = PCM_FORMAT_S16_LE,
266 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
267 .stop_threshold = INT_MAX,
268 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
269};
270
Ashish Jainf1eaa582016-05-23 20:54:24 +0530271#define AUDIO_MAX_PCM_FORMATS 7
272
273const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
274 [AUDIO_FORMAT_DEFAULT] = 0,
275 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
276 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
277 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
278 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
279 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
280 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
281};
282
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800283const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700284 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
285 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700286 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
287 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700288 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700289 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700290 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
291 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
292 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
293 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
294 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
295 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
296 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
297 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700298 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
299 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700300 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700301
Eric Laurentb23d5282013-05-14 15:27:20 -0700302 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700303 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530304 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
305 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
306 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530307 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
308 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700309 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700310 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700311 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700312 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700313
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800314 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800315 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700316 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700317
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700318 [USECASE_VOICE2_CALL] = "voice2-call",
319 [USECASE_VOLTE_CALL] = "volte-call",
320 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800321 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800322 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
323 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800324 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700325 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
326 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
327 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800328 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
329 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
330 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
331
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700332 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
333 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700334 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
335 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700336
337 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
338 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530339 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700340
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530341 /* Transcode loopback cases */
342 [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700343
344 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
345 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530346 /* For Interactive Audio Streams */
347 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
348 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
349 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
350 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
351 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
352 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
353 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
354 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700355
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800356 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
357
Balázs Triszka6e101332018-02-26 22:11:10 +0100358 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
359
360 /* For Elliptic Ultrasound proximity sensor */
361 [USECASE_AUDIO_ULTRASOUND_RX] = "ultrasound-rx",
362 [USECASE_AUDIO_ULTRASOUND_TX] = "ultrasound-tx",
Eric Laurentb23d5282013-05-14 15:27:20 -0700363};
364
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700365static const audio_usecase_t offload_usecases[] = {
366 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700367 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
368 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
369 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
370 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
371 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
372 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
373 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
374 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700375};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800376
Varun Balaraje49253e2017-07-06 19:48:56 +0530377static const audio_usecase_t interactive_usecases[] = {
378 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
379 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
380 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
381 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
382 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
383 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
384 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
385 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
386};
387
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800388#define STRING_TO_ENUM(string) { #string, string }
389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800390struct string_to_enum {
391 const char *name;
392 uint32_t value;
393};
394
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700395static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800396 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800397 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
398 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
399 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700400 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800401 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
402 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800403 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700404 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
405 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
406 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
407 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
408 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
409 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
410 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
411 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
412 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
413 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
414 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800415};
416
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700417static const struct string_to_enum formats_name_to_enum_table[] = {
418 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
419 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
420 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700421 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
422 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
423 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700424 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800425 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
426 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700427 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800428};
429
430//list of all supported sample rates by HDMI specification.
431static const int out_hdmi_sample_rates[] = {
432 32000, 44100, 48000, 88200, 96000, 176400, 192000,
433};
434
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700435static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800436 STRING_TO_ENUM(32000),
437 STRING_TO_ENUM(44100),
438 STRING_TO_ENUM(48000),
439 STRING_TO_ENUM(88200),
440 STRING_TO_ENUM(96000),
441 STRING_TO_ENUM(176400),
442 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700443};
444
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700445static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700446static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700447static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700448//cache last MBDRC cal step level
449static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700450
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530451static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
452static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuriebe78a72018-10-04 18:23:46 -0700453static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800454static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530455
Vatsal Buchaa1358992018-11-14 13:25:08 +0530456#ifdef AUDIO_FEATURE_ENABLED_GCOV
457extern void __gcov_flush();
458static void enable_gcov()
459{
460 __gcov_flush();
461}
462#else
463static void enable_gcov()
464{
465}
466#endif
467
Ramjee Singhacef98f2019-06-28 11:01:25 +0530468#if ANDROID_PLATFORM_SDK_VERSION >= 29
469static int in_set_microphone_direction(const struct audio_stream_in *stream,
470 audio_microphone_direction_t dir);
471static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
472#endif
473
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700474static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
475 int flags __unused)
476{
477 int dir = 0;
478 switch (uc_id) {
479 case USECASE_AUDIO_RECORD_LOW_LATENCY:
480 dir = 1;
481 case USECASE_AUDIO_PLAYBACK_ULL:
482 break;
483 default:
484 return false;
485 }
486
487 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
488 PCM_PLAYBACK : PCM_CAPTURE);
489 if (adev->adm_is_noirq_avail)
490 return adev->adm_is_noirq_avail(adev->adm_data,
491 adev->snd_card, dev_id, dir);
492 return false;
493}
494
495static void register_out_stream(struct stream_out *out)
496{
497 struct audio_device *adev = out->dev;
498 if (is_offload_usecase(out->usecase) ||
499 !adev->adm_register_output_stream)
500 return;
501
502 // register stream first for backward compatibility
503 adev->adm_register_output_stream(adev->adm_data,
504 out->handle,
505 out->flags);
506
507 if (!adev->adm_set_config)
508 return;
509
510 if (out->realtime)
511 adev->adm_set_config(adev->adm_data,
512 out->handle,
513 out->pcm, &out->config);
514}
515
516static void register_in_stream(struct stream_in *in)
517{
518 struct audio_device *adev = in->dev;
519 if (!adev->adm_register_input_stream)
520 return;
521
522 adev->adm_register_input_stream(adev->adm_data,
523 in->capture_handle,
524 in->flags);
525
526 if (!adev->adm_set_config)
527 return;
528
529 if (in->realtime)
530 adev->adm_set_config(adev->adm_data,
531 in->capture_handle,
532 in->pcm,
533 &in->config);
534}
535
536static void request_out_focus(struct stream_out *out, long ns)
537{
538 struct audio_device *adev = out->dev;
539
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700540 if (adev->adm_request_focus_v2)
541 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
542 else if (adev->adm_request_focus)
543 adev->adm_request_focus(adev->adm_data, out->handle);
544}
545
546static void request_in_focus(struct stream_in *in, long ns)
547{
548 struct audio_device *adev = in->dev;
549
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700550 if (adev->adm_request_focus_v2)
551 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
552 else if (adev->adm_request_focus)
553 adev->adm_request_focus(adev->adm_data, in->capture_handle);
554}
555
556static void release_out_focus(struct stream_out *out)
557{
558 struct audio_device *adev = out->dev;
559
560 if (adev->adm_abandon_focus)
561 adev->adm_abandon_focus(adev->adm_data, out->handle);
562}
563
564static void release_in_focus(struct stream_in *in)
565{
566 struct audio_device *adev = in->dev;
567 if (adev->adm_abandon_focus)
568 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
569}
570
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530571static int parse_snd_card_status(struct str_parms *parms, int *card,
572 card_status_t *status)
573{
574 char value[32]={0};
575 char state[32]={0};
576
577 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
578 if (ret < 0)
579 return -1;
580
581 // sscanf should be okay as value is of max length 32.
582 // same as sizeof state.
583 if (sscanf(value, "%d,%s", card, state) < 2)
584 return -1;
585
586 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
587 CARD_STATUS_OFFLINE;
588 return 0;
589}
590
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700591static inline void adjust_frames_for_device_delay(struct stream_out *out,
592 uint32_t *dsp_frames) {
593 // Adjustment accounts for A2dp encoder latency with offload usecases
594 // Note: Encoder latency is returned in ms.
595 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
596 unsigned long offset =
597 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
598 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
599 }
600}
601
vivek mehtaa76401a2015-04-24 14:12:15 -0700602__attribute__ ((visibility ("default")))
603bool audio_hw_send_gain_dep_calibration(int level) {
604 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700605 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700606
607 pthread_mutex_lock(&adev_init_lock);
608
609 if (adev != NULL && adev->platform != NULL) {
610 pthread_mutex_lock(&adev->lock);
611 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700612
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530613 // cache level info for any of the use case which
614 // was not started.
615 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700616
vivek mehtaa76401a2015-04-24 14:12:15 -0700617 pthread_mutex_unlock(&adev->lock);
618 } else {
619 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
620 }
621
622 pthread_mutex_unlock(&adev_init_lock);
623
624 return ret_val;
625}
626
Ashish Jain5106d362016-05-11 19:23:33 +0530627static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
628{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800629 bool gapless_enabled = false;
630 const char *mixer_ctl_name = "Compress Gapless Playback";
631 struct mixer_ctl *ctl;
632
633 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700634 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530635
636 /*Disable gapless if its AV playback*/
637 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800638
639 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
640 if (!ctl) {
641 ALOGE("%s: Could not get ctl for mixer cmd - %s",
642 __func__, mixer_ctl_name);
643 return -EINVAL;
644 }
645
646 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
647 ALOGE("%s: Could not set gapless mode %d",
648 __func__, gapless_enabled);
649 return -EINVAL;
650 }
651 return 0;
652}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700653
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700654__attribute__ ((visibility ("default")))
655int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
656 int table_size) {
657 int ret_val = 0;
658 ALOGV("%s: enter ... ", __func__);
659
660 pthread_mutex_lock(&adev_init_lock);
661 if (adev == NULL) {
662 ALOGW("%s: adev is NULL .... ", __func__);
663 goto done;
664 }
665
666 pthread_mutex_lock(&adev->lock);
667 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
668 pthread_mutex_unlock(&adev->lock);
669done:
670 pthread_mutex_unlock(&adev_init_lock);
671 ALOGV("%s: exit ... ", __func__);
672 return ret_val;
673}
674
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700675static bool is_supported_format(audio_format_t format)
676{
Eric Laurent86e17132013-09-12 17:49:30 -0700677 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530678 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530679 format == AUDIO_FORMAT_AAC_LC ||
680 format == AUDIO_FORMAT_AAC_HE_V1 ||
681 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530682 format == AUDIO_FORMAT_AAC_ADTS_LC ||
683 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
684 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530685 format == AUDIO_FORMAT_AAC_LATM_LC ||
686 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
687 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530688 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
689 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530690 format == AUDIO_FORMAT_PCM_FLOAT ||
691 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700692 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530693 format == AUDIO_FORMAT_AC3 ||
694 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700695 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530696 format == AUDIO_FORMAT_DTS ||
697 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800698 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530699 format == AUDIO_FORMAT_ALAC ||
700 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530701 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530702 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800703 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530704 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700705 format == AUDIO_FORMAT_APTX ||
706 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800707 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700708
709 return false;
710}
711
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700712static inline bool is_mmap_usecase(audio_usecase_t uc_id)
713{
714 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
715 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
716}
717
Avinash Vaish71a8b972014-07-24 15:36:33 +0530718static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
719 struct audio_usecase *uc_info)
720{
721 struct listnode *node;
722 struct audio_usecase *usecase;
723
724 if (uc_info == NULL)
725 return -EINVAL;
726
727 /* Re-route all voice usecases on the shared backend other than the
728 specified usecase to new snd devices */
729 list_for_each(node, &adev->usecase_list) {
730 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800731 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530732 enable_audio_route(adev, usecase);
733 }
734 return 0;
735}
736
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530737static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530738{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530739 ALOGV("%s", __func__);
740 audio_route_apply_and_update_path(adev->audio_route,
741 "asrc-mode");
742 adev->asrc_mode_enabled = true;
743}
744
745static void disable_asrc_mode(struct audio_device *adev)
746{
747 ALOGV("%s", __func__);
748 audio_route_reset_and_update_path(adev->audio_route,
749 "asrc-mode");
750 adev->asrc_mode_enabled = false;
751}
752
753/*
754 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
755 * 44.1 or Native DSD backends are enabled for any of current use case.
756 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
757 * - Disable current mix path use case(Headphone backend) and re-enable it with
758 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
759 * e.g. Naitve DSD or Headphone 44.1 -> + 48
760 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530761static void check_and_set_asrc_mode(struct audio_device *adev,
762 struct audio_usecase *uc_info,
763 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530764{
765 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530766 int i, num_new_devices = 0;
767 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
768 /*
769 *Split snd device for new combo use case
770 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
771 */
772 if (platform_split_snd_device(adev->platform,
773 snd_device,
774 &num_new_devices,
775 split_new_snd_devices) == 0) {
776 for (i = 0; i < num_new_devices; i++)
777 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
778 } else {
779 int new_backend_idx = platform_get_backend_index(snd_device);
780 if (((new_backend_idx == HEADPHONE_BACKEND) ||
781 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
782 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
783 !adev->asrc_mode_enabled) {
784 struct listnode *node = NULL;
785 struct audio_usecase *uc = NULL;
786 struct stream_out *curr_out = NULL;
787 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
788 int i, num_devices, ret = 0;
789 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530790
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530791 list_for_each(node, &adev->usecase_list) {
792 uc = node_to_item(node, struct audio_usecase, list);
793 curr_out = (struct stream_out*) uc->stream.out;
794 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
795 /*
796 *Split snd device for existing combo use case
797 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
798 */
799 ret = platform_split_snd_device(adev->platform,
800 uc->out_snd_device,
801 &num_devices,
802 split_snd_devices);
803 if (ret < 0 || num_devices == 0) {
804 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
805 split_snd_devices[0] = uc->out_snd_device;
806 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800807 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530808 for (i = 0; i < num_devices; i++) {
809 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
810 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
811 if((new_backend_idx == HEADPHONE_BACKEND) &&
812 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
813 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
814 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
815 __func__);
816 enable_asrc_mode(adev);
817 break;
818 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
819 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
820 (usecase_backend_idx == HEADPHONE_BACKEND)) {
821 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
822 __func__);
823 disable_audio_route(adev, uc);
824 disable_snd_device(adev, uc->out_snd_device);
825 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
826 if (new_backend_idx == DSD_NATIVE_BACKEND)
827 audio_route_apply_and_update_path(adev->audio_route,
828 "hph-true-highquality-mode");
829 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
830 (curr_out->bit_width >= 24))
831 audio_route_apply_and_update_path(adev->audio_route,
832 "hph-highquality-mode");
833 enable_asrc_mode(adev);
834 enable_snd_device(adev, uc->out_snd_device);
835 enable_audio_route(adev, uc);
836 break;
837 }
838 }
839 // reset split devices count
840 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800841 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530842 if (adev->asrc_mode_enabled)
843 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530844 }
845 }
846 }
847}
848
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700849#ifdef DYNAMIC_ECNS_ENABLED
850static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
851 struct audio_effect_config effect_config,
852 unsigned int param_value)
853{
854 char mixer_ctl_name[] = "Audio Effect";
855 struct mixer_ctl *ctl;
856 long set_values[6];
857 struct stream_in *in = adev->active_input;
858
859 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
860 if (!ctl) {
861 ALOGE("%s: Could not get mixer ctl - %s",
862 __func__, mixer_ctl_name);
863 return -EINVAL;
864 }
865
866 set_values[0] = 1; //0:Rx 1:Tx
867 set_values[1] = in->app_type_cfg.app_type;
868 set_values[2] = (long)effect_config.module_id;
869 set_values[3] = (long)effect_config.instance_id;
870 set_values[4] = (long)effect_config.param_id;
871 set_values[5] = param_value;
872
873 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
874
875 return 0;
876
877}
878
879static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
880 int effect_type, unsigned int *param_value)
881{
882 int ret = 0;
883 struct audio_effect_config other_effect_config;
884 struct audio_usecase *usecase = NULL;
885 struct stream_in *in = adev->active_input;
886
887 usecase = get_usecase_from_list(adev, in->usecase);
888 if (!usecase)
889 return -EINVAL;
890
891 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
892 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
893 if (ret < 0) {
894 ALOGE("%s Failed to get effect params %d", __func__, ret);
895 return ret;
896 }
897
898 if (module_id == other_effect_config.module_id) {
899 //Same module id for AEC/NS. Values need to be combined
900 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
901 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
902 *param_value |= other_effect_config.param_value;
903 }
904 }
905
906 return ret;
907}
908
909static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
910{
911 struct audio_effect_config effect_config;
912 struct audio_usecase *usecase = NULL;
913 int ret = 0;
914 unsigned int param_value = 0;
915 struct stream_in *in = adev->active_input;
916
917 if (!in) {
918 ALOGE("%s: Invalid input stream", __func__);
919 return -EINVAL;
920 }
921
922 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
923
924 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800925 if (usecase == NULL) {
926 ALOGE("%s: Could not find the usecase (%d) in the list",
927 __func__, in->usecase);
928 return -EINVAL;
929 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700930
931 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
932 if (ret < 0) {
933 ALOGE("%s Failed to get module id %d", __func__, ret);
934 return ret;
935 }
936 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
937 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
938
939 if(enable)
940 param_value = effect_config.param_value;
941
942 /*Special handling for AEC & NS effects Param values need to be
943 updated if module ids are same*/
944
945 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
946 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
947 if (ret < 0)
948 return ret;
949 }
950
951 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
952
953 return ret;
954}
955
956static void check_and_enable_effect(struct audio_device *adev)
957{
958
959 if (adev->active_input->enable_aec) {
960 enable_disable_effect(adev, EFFECT_AEC, true);
961 }
962
963 if (adev->active_input->enable_ns &&
964 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
965 enable_disable_effect(adev, EFFECT_NS, true);
966 }
967}
968#else
969#define enable_disable_effect(x, y, z) ENOSYS
970#define check_and_enable_effect(x) ENOSYS
971#endif
972
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700973int pcm_ioctl(struct pcm *pcm, int request, ...)
974{
975 va_list ap;
976 void * arg;
977 int pcm_fd = *(int*)pcm;
978
979 va_start(ap, request);
980 arg = va_arg(ap, void *);
981 va_end(ap);
982
983 return ioctl(pcm_fd, request, arg);
984}
985
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700986int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700987 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800988{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700989 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700990 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530991 struct stream_out *out = NULL;
Soumya Managolie7651c42018-06-28 16:04:57 +0530992 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800993
994 if (usecase == NULL)
995 return -EINVAL;
996
997 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
998
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800999 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001000 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001001 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001002 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001003
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001004#ifdef DS1_DOLBY_DAP_ENABLED
1005 audio_extn_dolby_set_dmid(adev);
1006 audio_extn_dolby_set_endpoint(adev);
1007#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001008 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001009 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301010 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001011 audio_extn_utils_send_app_type_cfg(adev, usecase);
Balázs Triszka6e101332018-02-26 22:11:10 +01001012#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1013 if (usecase->id != USECASE_AUDIO_ULTRASOUND_TX)
1014#endif
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301015 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301016 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1017 out = usecase->stream.out;
1018 if (out && out->compr)
1019 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1020 }
Dhananjay Kumar2a7f75b2018-12-10 22:26:53 +05301021 audio_extn_set_custom_mtmx_params(adev, usecase, true);
Manish Dewangan58229382017-02-02 15:48:41 +05301022
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001023 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001024 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001025 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managolie7651c42018-06-28 16:04:57 +05301026 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1027 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1028 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1029 if (parms) {
1030 audio_extn_fm_set_parameters(adev, parms);
1031 str_parms_destroy(parms);
1032 }
1033 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001034 ALOGV("%s: exit", __func__);
1035 return 0;
1036}
1037
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001038int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001039 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001040{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001041 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001042 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001043
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301044 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001045 return -EINVAL;
1046
1047 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001048 if (usecase->type == PCM_CAPTURE)
1049 snd_device = usecase->in_snd_device;
1050 else
1051 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001052 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001053 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001054 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001055 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001056 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301057 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Dhananjay Kumar2a7f75b2018-12-10 22:26:53 +05301058 audio_extn_set_custom_mtmx_params(adev, usecase, false);
Weiyin Jiange2938532019-06-03 14:29:30 +08001059 if ((usecase->type == PCM_PLAYBACK) &&
1060 (usecase->stream.out != NULL))
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05301061 usecase->stream.out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001062 ALOGV("%s: exit", __func__);
1063 return 0;
1064}
1065
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001066int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001067 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301069 int i, num_devices = 0;
1070 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001071 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1072
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001073 if (snd_device < SND_DEVICE_MIN ||
1074 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001075 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001076 return -EINVAL;
1077 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001078
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001079 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001080 ALOGE("%s: Invalid sound device returned", __func__);
1081 return -EINVAL;
1082 }
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001083
1084 adev->snd_dev_ref_cnt[snd_device]++;
1085
1086 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1087 (platform_split_snd_device(adev->platform,
1088 snd_device,
1089 &num_devices,
1090 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001091 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001092 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001093 return 0;
1094 }
1095
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001096 if (audio_extn_spkr_prot_is_enabled())
1097 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001098
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001099 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1100 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001101 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1102 goto err;
1103 }
1104 audio_extn_dev_arbi_acquire(snd_device);
1105 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001106 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001107 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001108 goto err;
1109 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001110 } else if (platform_split_snd_device(adev->platform,
1111 snd_device,
1112 &num_devices,
1113 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301114 for (i = 0; i < num_devices; i++) {
1115 enable_snd_device(adev, new_snd_devices[i]);
1116 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001117 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001118 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301119
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301120
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001121 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1122 (audio_extn_a2dp_start_playback() < 0)) {
1123 ALOGE(" fail to configure A2dp control path ");
1124 goto err;
1125 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301126
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001127 /* due to the possibility of calibration overwrite between listen
1128 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001129 audio_extn_sound_trigger_update_device_status(snd_device,
1130 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301131 audio_extn_listen_update_device_status(snd_device,
1132 LISTEN_EVENT_SND_DEVICE_BUSY);
Balázs Triszka6e101332018-02-26 22:11:10 +01001133#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1134 if (snd_device != SND_DEVICE_OUT_ULTRASOUND_HANDSET &&
1135 snd_device != SND_DEVICE_IN_ULTRASOUND_MIC)
1136#endif
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001137 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001138 audio_extn_sound_trigger_update_device_status(snd_device,
1139 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301140 audio_extn_listen_update_device_status(snd_device,
1141 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001142 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001143 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001144 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001145 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301146
1147 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1148 !adev->native_playback_enabled &&
1149 audio_is_true_native_stream_active(adev)) {
1150 ALOGD("%s: %d: napb: enabling native mode in hardware",
1151 __func__, __LINE__);
1152 audio_route_apply_and_update_path(adev->audio_route,
1153 "true-native-mode");
1154 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301155 }
Dhanalakshmi Siddani0f1dfd52019-01-09 12:38:13 +05301156 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1157 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001158 (audio_extn_ffv_get_stream() == adev->active_input)) {
1159 ALOGD("%s: init ec ref loopback", __func__);
1160 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1161 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001162 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001163 return 0;
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001164err:
1165 adev->snd_dev_ref_cnt[snd_device]--;
1166 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001167}
1168
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001169int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001170 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001171{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301172 int i, num_devices = 0;
1173 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001174 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1175
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001176 if (snd_device < SND_DEVICE_MIN ||
1177 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001178 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001179 return -EINVAL;
1180 }
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001181
1182 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1183 ALOGE("%s: Invalid sound device returned", __func__);
1184 return -EINVAL;
1185 }
1186
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001187 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1188 ALOGE("%s: device ref cnt is already 0", __func__);
1189 return -EINVAL;
1190 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001191
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001192 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001193
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001194 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001195 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301196
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001197 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1198 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001199 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001200
1201 // when speaker device is disabled, reset swap.
1202 // will be renabled on usecase start
1203 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001204 } else if (platform_split_snd_device(adev->platform,
1205 snd_device,
1206 &num_devices,
1207 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301208 for (i = 0; i < num_devices; i++) {
1209 disable_snd_device(adev, new_snd_devices[i]);
1210 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001211 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001212 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001213 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001214
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301215 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1216 audio_extn_a2dp_stop_playback();
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001217 else if (snd_device == SND_DEVICE_OUT_HDMI ||
1218 snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301219 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301220 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001221 adev->native_playback_enabled) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301222 ALOGD("%s: %d: napb: disabling native mode in hardware",
1223 __func__, __LINE__);
1224 audio_route_reset_and_update_path(adev->audio_route,
1225 "true-native-mode");
1226 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301227 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001228 adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301229 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301230 disable_asrc_mode(adev);
1231 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001232 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1233 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
1234 (audio_extn_ffv_get_stream() == adev->active_input)) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001235 ALOGD("%s: deinit ec ref loopback", __func__);
1236 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1237 }
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001238
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001239 audio_extn_utils_release_snd_device(snd_device);
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001240 } else {
1241 if (platform_split_snd_device(adev->platform,
1242 snd_device,
1243 &num_devices,
1244 new_snd_devices) == 0) {
1245 for (i = 0; i < num_devices; i++) {
1246 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1247 }
1248 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001249 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001250
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001251 return 0;
1252}
1253
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001254/*
1255 legend:
1256 uc - existing usecase
1257 new_uc - new usecase
1258 d1, d11, d2 - SND_DEVICE enums
1259 a1, a2 - corresponding ANDROID device enums
1260 B1, B2 - backend strings
1261
1262case 1
1263 uc->dev d1 (a1) B1
1264 new_uc->dev d1 (a1), d2 (a2) B1, B2
1265
1266 resolution: disable and enable uc->dev on d1
1267
1268case 2
1269 uc->dev d1 (a1) B1
1270 new_uc->dev d11 (a1) B1
1271
1272 resolution: need to switch uc since d1 and d11 are related
1273 (e.g. speaker and voice-speaker)
1274 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1275
1276case 3
1277 uc->dev d1 (a1) B1
1278 new_uc->dev d2 (a2) B2
1279
1280 resolution: no need to switch uc
1281
1282case 4
1283 uc->dev d1 (a1) B1
1284 new_uc->dev d2 (a2) B1
1285
1286 resolution: disable enable uc-dev on d2 since backends match
1287 we cannot enable two streams on two different devices if they
1288 share the same backend. e.g. if offload is on speaker device using
1289 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1290 using the same backend, offload must also be switched to voice-handset.
1291
1292case 5
1293 uc->dev d1 (a1) B1
1294 new_uc->dev d1 (a1), d2 (a2) B1
1295
1296 resolution: disable enable uc-dev on d2 since backends match
1297 we cannot enable two streams on two different devices if they
1298 share the same backend.
1299
1300case 6
1301 uc->dev d1 (a1) B1
1302 new_uc->dev d2 (a1) B2
1303
1304 resolution: no need to switch
1305
1306case 7
1307 uc->dev d1 (a1), d2 (a2) B1, B2
1308 new_uc->dev d1 (a1) B1
1309
1310 resolution: no need to switch
1311
Zhou Song4ba65882018-07-09 14:48:07 +08001312case 8
1313 uc->dev d1 (a1) B1
1314 new_uc->dev d11 (a1), d2 (a2) B1, B2
1315 resolution: compared to case 1, for this case, d1 and d11 are related
1316 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001317*/
1318static snd_device_t derive_playback_snd_device(void * platform,
1319 struct audio_usecase *uc,
1320 struct audio_usecase *new_uc,
1321 snd_device_t new_snd_device)
1322{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301323 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001324
1325 snd_device_t d1 = uc->out_snd_device;
1326 snd_device_t d2 = new_snd_device;
1327
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301328 switch (uc->type) {
1329 case TRANSCODE_LOOPBACK :
1330 a1 = uc->stream.inout->out_config.devices;
1331 a2 = new_uc->stream.inout->out_config.devices;
1332 break;
1333 default :
1334 a1 = uc->stream.out->devices;
1335 a2 = new_uc->stream.out->devices;
1336 break;
1337 }
1338
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001339 // Treat as a special case when a1 and a2 are not disjoint
1340 if ((a1 != a2) && (a1 & a2)) {
1341 snd_device_t d3[2];
1342 int num_devices = 0;
1343 int ret = platform_split_snd_device(platform,
1344 popcount(a1) > 1 ? d1 : d2,
1345 &num_devices,
1346 d3);
1347 if (ret < 0) {
1348 if (ret != -ENOSYS) {
1349 ALOGW("%s failed to split snd_device %d",
1350 __func__,
1351 popcount(a1) > 1 ? d1 : d2);
1352 }
1353 goto end;
1354 }
1355
1356 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1357 // But if it does happen, we need to give priority to d2 if
1358 // the combo devices active on the existing usecase share a backend.
1359 // This is because we cannot have a usecase active on a combo device
1360 // and a new usecase requests one device in this combo pair.
1361 if (platform_check_backends_match(d3[0], d3[1])) {
1362 return d2; // case 5
1363 } else {
Zhou Song671be042018-08-27 15:33:52 +08001364 // check if d1 is related to any of d3's OR
1365 // old uc is combo device but new_uc is one of the combo device
1366 if (d1 == d3[0] || d1 == d3[1] || popcount(a1) > 1)
1367 return d1; // case 1, 7
Zhou Song4ba65882018-07-09 14:48:07 +08001368 else
1369 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001370 }
1371 } else {
1372 if (platform_check_backends_match(d1, d2)) {
1373 return d2; // case 2, 4
1374 } else {
1375 return d1; // case 6, 3
1376 }
1377 }
1378
1379end:
1380 return d2; // return whatever was calculated before.
1381}
1382
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001383static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301384 struct audio_usecase *uc_info,
1385 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001386{
1387 struct listnode *node;
1388 struct audio_usecase *usecase;
1389 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301390 snd_device_t uc_derive_snd_device;
1391 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001392 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1393 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001394 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301395 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001396 /*
1397 * This function is to make sure that all the usecases that are active on
1398 * the hardware codec backend are always routed to any one device that is
1399 * handled by the hardware codec.
1400 * For example, if low-latency and deep-buffer usecases are currently active
1401 * on speaker and out_set_parameters(headset) is received on low-latency
1402 * output, then we have to make sure deep-buffer is also switched to headset,
1403 * because of the limitation that both the devices cannot be enabled
1404 * at the same time as they share the same backend.
1405 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001406 /*
1407 * This call is to check if we need to force routing for a particular stream
1408 * If there is a backend configuration change for the device when a
1409 * new stream starts, then ADM needs to be closed and re-opened with the new
1410 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001411 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001412 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001413 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1414 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301415 /* For a2dp device reconfigure all active sessions
1416 * with new AFE encoder format based on a2dp state
1417 */
1418 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1419 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1420 audio_extn_a2dp_is_force_device_switch()) {
1421 force_routing = true;
1422 force_restart_session = true;
1423 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301424 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1425
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001426 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001427 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001428 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001429 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1430 switch_device[i] = false;
1431
1432 list_for_each(node, &adev->usecase_list) {
1433 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001434
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301435 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1436 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301437 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301438 platform_get_snd_device_name(usecase->out_snd_device),
1439 platform_check_backends_match(snd_device, usecase->out_snd_device));
Balázs Triszka6e101332018-02-26 22:11:10 +01001440
1441#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1442 if (usecase->id == USECASE_AUDIO_ULTRASOUND_RX)
1443 continue;
1444#endif
1445
Ashish Jain6a65b352017-03-21 17:24:40 +05301446 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1447 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1448 usecase, uc_info, snd_device);
1449 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1450 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1451 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1452 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001453 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301454 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1455 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1456 ((force_restart_session) ||
1457 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301458 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1459 __func__, use_case_table[usecase->id],
1460 platform_get_snd_device_name(usecase->out_snd_device));
1461 disable_audio_route(adev, usecase);
1462 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301463 /* Enable existing usecase on derived playback device */
1464 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301465 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301466 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 }
1468 }
1469
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301470 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1471 num_uc_to_switch);
1472
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001473 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001474 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001475
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301476 /* Make sure the previous devices to be disabled first and then enable the
1477 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001478 list_for_each(node, &adev->usecase_list) {
1479 usecase = node_to_item(node, struct audio_usecase, list);
1480 if (switch_device[usecase->id]) {
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001481 /* Check if output sound device to be switched can be split and if any
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001482 of the split devices match with derived sound device */
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001483 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1484 &num_devices, split_snd_devices) == 0) {
1485 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001486 for (i = 0; i < num_devices; i++) {
1487 /* Disable devices that do not match with derived sound device */
1488 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1489 disable_snd_device(adev, split_snd_devices[i]);
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001490 }
1491 } else {
1492 disable_snd_device(adev, usecase->out_snd_device);
1493 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001494 }
1495 }
1496
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001497 list_for_each(node, &adev->usecase_list) {
1498 usecase = node_to_item(node, struct audio_usecase, list);
1499 if (switch_device[usecase->id]) {
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001500 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1501 &num_devices, split_snd_devices) == 0) {
1502 /* Enable derived sound device only if it does not match with
1503 one of the split sound devices. This is because the matching
1504 sound device was not disabled */
1505 bool should_enable = true;
1506 for (i = 0; i < num_devices; i++) {
1507 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1508 should_enable = false;
1509 break;
1510 }
1511 }
1512 if (should_enable)
1513 enable_snd_device(adev, derive_snd_device[usecase->id]);
1514 } else {
1515 enable_snd_device(adev, derive_snd_device[usecase->id]);
1516 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001517 }
1518 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001519
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001520 /* Re-route all the usecases on the shared backend other than the
1521 specified usecase to new snd devices */
1522 list_for_each(node, &adev->usecase_list) {
1523 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301524 /* Update the out_snd_device only before enabling the audio route */
1525 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301526 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301527 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301528 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301529 use_case_table[usecase->id],
1530 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001531 /* Update voc calibration before enabling VoIP route */
1532 if (usecase->type == VOIP_CALL)
1533 status = platform_switch_voice_call_device_post(adev->platform,
1534 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001535 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301536 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001537 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1538 out_set_voip_volume(&usecase->stream.out->stream,
1539 usecase->stream.out->volume_l,
1540 usecase->stream.out->volume_r);
1541 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301542 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001543 }
1544 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001545 }
1546}
1547
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301548static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001549 struct audio_usecase *uc_info,
1550 snd_device_t snd_device)
1551{
1552 struct listnode *node;
1553 struct audio_usecase *usecase;
1554 bool switch_device[AUDIO_USECASE_MAX];
1555 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301556 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001557 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001558
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301559 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1560 snd_device);
1561 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301562
1563 /*
1564 * Make sure out devices is checked against out codec backend device and
1565 * also in devices against in codec backend. Checking out device against in
1566 * codec backend or vice versa causes issues.
1567 */
1568 if (uc_info->type == PCM_CAPTURE)
1569 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001570 /*
1571 * This function is to make sure that all the active capture usecases
1572 * are always routed to the same input sound device.
1573 * For example, if audio-record and voice-call usecases are currently
1574 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1575 * is received for voice call then we have to make sure that audio-record
1576 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1577 * because of the limitation that two devices cannot be enabled
1578 * at the same time if they share the same backend.
1579 */
1580 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1581 switch_device[i] = false;
1582
1583 list_for_each(node, &adev->usecase_list) {
1584 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301585 /*
1586 * TODO: Enhance below condition to handle BT sco/USB multi recording
1587 */
Balázs Triszka6e101332018-02-26 22:11:10 +01001588
1589#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1590 if (usecase->id == USECASE_AUDIO_ULTRASOUND_TX)
1591 continue;
1592#endif
1593
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001594 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001595 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301596 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301597 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301598 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301599 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001600 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001601 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1602 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001603 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001604 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001605 switch_device[usecase->id] = true;
1606 num_uc_to_switch++;
1607 }
1608 }
1609
1610 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001611 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001612
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301613 /* Make sure the previous devices to be disabled first and then enable the
1614 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001615 list_for_each(node, &adev->usecase_list) {
1616 usecase = node_to_item(node, struct audio_usecase, list);
1617 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001618 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001619 }
1620 }
1621
1622 list_for_each(node, &adev->usecase_list) {
1623 usecase = node_to_item(node, struct audio_usecase, list);
1624 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001625 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001626 }
1627 }
1628
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001629 /* Re-route all the usecases on the shared backend other than the
1630 specified usecase to new snd devices */
1631 list_for_each(node, &adev->usecase_list) {
1632 usecase = node_to_item(node, struct audio_usecase, list);
1633 /* Update the in_snd_device only before enabling the audio route */
1634 if (switch_device[usecase->id] ) {
1635 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001636 if (usecase->type != VOICE_CALL) {
1637 /* Update voc calibration before enabling VoIP route */
1638 if (usecase->type == VOIP_CALL)
1639 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001640 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001641 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301642 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001643 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001644 }
1645 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001646 }
1647}
1648
Mingming Yin3a941d42016-02-17 18:08:05 -08001649static void reset_hdmi_sink_caps(struct stream_out *out) {
1650 int i = 0;
1651
1652 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1653 out->supported_channel_masks[i] = 0;
1654 }
1655 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1656 out->supported_formats[i] = 0;
1657 }
1658 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1659 out->supported_sample_rates[i] = 0;
1660 }
1661}
1662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001663/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001664static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001665{
Mingming Yin3a941d42016-02-17 18:08:05 -08001666 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001667 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001668
Mingming Yin3a941d42016-02-17 18:08:05 -08001669 reset_hdmi_sink_caps(out);
1670
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001671 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001672 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001673 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001674 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001675 }
1676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001677 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001679 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001680 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001681 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1682 case 6:
1683 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1684 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1685 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1686 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1687 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1688 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689 break;
1690 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001691 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001692 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001693 break;
1694 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001695
1696 // check channel format caps
1697 i = 0;
1698 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1699 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1700 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1701 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1702 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1703 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1704 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1705 }
1706
Ben Romberger1aaaf862017-04-06 17:49:46 -07001707 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1708 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1709 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1710 }
1711
Mingming Yin3a941d42016-02-17 18:08:05 -08001712 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1713 ALOGV(":%s HDMI supports DTS format", __func__);
1714 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1715 }
1716
1717 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1718 ALOGV(":%s HDMI supports DTS HD format", __func__);
1719 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1720 }
1721
Naresh Tanniru928f0862017-04-07 16:44:23 -07001722 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1723 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1724 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1725 }
1726
Mingming Yin3a941d42016-02-17 18:08:05 -08001727
1728 // check sample rate caps
1729 i = 0;
1730 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1731 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1732 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1733 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1734 }
1735 }
1736
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001737 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738}
1739
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001740static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1741 uint32_t *supported_sample_rates __unused,
1742 uint32_t max_rates __unused)
1743{
1744 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1745 supported_sample_rates,
1746 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301747 ssize_t i = 0;
1748
1749 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001750 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1751 supported_sample_rates[i]);
1752 }
1753 return count;
1754}
1755
1756static inline int read_usb_sup_channel_masks(bool is_playback,
1757 audio_channel_mask_t *supported_channel_masks,
1758 uint32_t max_masks)
1759{
1760 int channels = audio_extn_usb_get_max_channels(is_playback);
1761 int channel_count;
1762 uint32_t num_masks = 0;
1763 if (channels > MAX_HIFI_CHANNEL_COUNT)
1764 channels = MAX_HIFI_CHANNEL_COUNT;
1765
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301766 channel_count = DEFAULT_CHANNEL_COUNT;
1767
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001768 if (is_playback) {
1769 // For playback we never report mono because the framework always outputs stereo
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001770 // audio_channel_out_mask_from_count() does return positional masks for channel counts
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301771 // above 2 but we want indexed masks here.
1772 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001773 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001774 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1775 // indexed mask
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301776 supported_channel_masks[num_masks++] = audio_channel_in_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001777 }
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301778
1779 for (channel_count = channels; ((channel_count >= DEFAULT_CHANNEL_COUNT) &&
1780 (num_masks < max_masks)); channel_count--) {
1781 supported_channel_masks[num_masks++] =
1782 audio_channel_mask_for_index_assignment_from_count(channel_count);
1783 }
1784
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001785 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1786 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1787 return num_masks;
1788}
1789
1790static inline int read_usb_sup_formats(bool is_playback __unused,
1791 audio_format_t *supported_formats,
1792 uint32_t max_formats __unused)
1793{
1794 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1795 switch (bitwidth) {
1796 case 24:
1797 // XXX : usb.c returns 24 for s24 and s24_le?
1798 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1799 break;
1800 case 32:
1801 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1802 break;
1803 case 16:
1804 default :
1805 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1806 break;
1807 }
1808 ALOGV("%s: %s supported format %d", __func__,
1809 is_playback ? "P" : "C", bitwidth);
1810 return 1;
1811}
1812
1813static inline int read_usb_sup_params_and_compare(bool is_playback,
1814 audio_format_t *format,
1815 audio_format_t *supported_formats,
1816 uint32_t max_formats,
1817 audio_channel_mask_t *mask,
1818 audio_channel_mask_t *supported_channel_masks,
1819 uint32_t max_masks,
1820 uint32_t *rate,
1821 uint32_t *supported_sample_rates,
1822 uint32_t max_rates) {
1823 int ret = 0;
1824 int num_formats;
1825 int num_masks;
1826 int num_rates;
1827 int i;
1828
1829 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1830 max_formats);
1831 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1832 max_masks);
1833
1834 num_rates = read_usb_sup_sample_rates(is_playback,
1835 supported_sample_rates, max_rates);
1836
1837#define LUT(table, len, what, dflt) \
1838 for (i=0; i<len && (table[i] != what); i++); \
1839 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1840
1841 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1842 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1843 LUT(supported_sample_rates, num_rates, *rate, 0);
1844
1845#undef LUT
1846 return ret < 0 ? -EINVAL : 0; // HACK TBD
1847}
1848
Alexy Josephb1379942016-01-29 15:49:38 -08001849audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001850 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001851{
1852 struct audio_usecase *usecase;
1853 struct listnode *node;
1854
1855 list_for_each(node, &adev->usecase_list) {
1856 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001857 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001858 ALOGV("%s: usecase id %d", __func__, usecase->id);
1859 return usecase->id;
1860 }
1861 }
1862 return USECASE_INVALID;
1863}
1864
Alexy Josephb1379942016-01-29 15:49:38 -08001865struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001866 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001867{
1868 struct audio_usecase *usecase;
1869 struct listnode *node;
1870
1871 list_for_each(node, &adev->usecase_list) {
1872 usecase = node_to_item(node, struct audio_usecase, list);
1873 if (usecase->id == uc_id)
1874 return usecase;
1875 }
1876 return NULL;
1877}
1878
Dhananjay Kumard4833242016-10-06 22:09:12 +05301879struct stream_in *get_next_active_input(const struct audio_device *adev)
1880{
1881 struct audio_usecase *usecase;
1882 struct listnode *node;
1883
1884 list_for_each_reverse(node, &adev->usecase_list) {
1885 usecase = node_to_item(node, struct audio_usecase, list);
1886 if (usecase->type == PCM_CAPTURE)
1887 return usecase->stream.in;
1888 }
1889 return NULL;
1890}
1891
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301892/*
1893 * is a true native playback active
1894 */
1895bool audio_is_true_native_stream_active(struct audio_device *adev)
1896{
1897 bool active = false;
1898 int i = 0;
1899 struct listnode *node;
1900
1901 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1902 ALOGV("%s:napb: not in true mode or non hdphones device",
1903 __func__);
1904 active = false;
1905 goto exit;
1906 }
1907
1908 list_for_each(node, &adev->usecase_list) {
1909 struct audio_usecase *uc;
1910 uc = node_to_item(node, struct audio_usecase, list);
1911 struct stream_out *curr_out =
1912 (struct stream_out*) uc->stream.out;
1913
1914 if (curr_out && PCM_PLAYBACK == uc->type) {
1915 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1916 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1917 uc->id, curr_out->sample_rate,
1918 curr_out->bit_width,
1919 platform_get_snd_device_name(uc->out_snd_device));
1920
1921 if (is_offload_usecase(uc->id) &&
1922 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1923 active = true;
1924 ALOGD("%s:napb:native stream detected", __func__);
1925 }
1926 }
1927 }
1928exit:
1929 return active;
1930}
1931
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001932uint32_t adev_get_dsp_bit_width_enforce_mode()
1933{
1934 if (adev == NULL) {
1935 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1936 return 0;
1937 }
1938 return adev->dsp_bit_width_enforce_mode;
1939}
1940
1941static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1942{
1943 char value[PROPERTY_VALUE_MAX];
1944 int trial;
1945 uint32_t dsp_bit_width_enforce_mode = 0;
1946
1947 if (!mixer) {
1948 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1949 __func__);
1950 return 0;
1951 }
1952
1953 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1954 value, NULL) > 0) {
1955 trial = atoi(value);
1956 switch (trial) {
1957 case 16:
1958 dsp_bit_width_enforce_mode = 16;
1959 break;
1960 case 24:
1961 dsp_bit_width_enforce_mode = 24;
1962 break;
1963 case 32:
1964 dsp_bit_width_enforce_mode = 32;
1965 break;
1966 default:
1967 dsp_bit_width_enforce_mode = 0;
1968 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1969 break;
1970 }
1971 }
1972
1973 return dsp_bit_width_enforce_mode;
1974}
1975
1976static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1977 uint32_t enforce_mode,
1978 bool enable)
1979{
1980 struct mixer_ctl *ctl = NULL;
1981 const char *mixer_ctl_name = "ASM Bit Width";
1982 uint32_t asm_bit_width_mode = 0;
1983
1984 if (enforce_mode == 0) {
1985 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1986 return;
1987 }
1988
1989 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1990 if (!ctl) {
1991 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1992 __func__, mixer_ctl_name);
1993 return;
1994 }
1995
1996 if (enable)
1997 asm_bit_width_mode = enforce_mode;
1998 else
1999 asm_bit_width_mode = 0;
2000
2001 ALOGV("%s DSP bit width feature status is %d width=%d",
2002 __func__, enable, asm_bit_width_mode);
2003 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2004 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2005 asm_bit_width_mode);
2006
2007 return;
2008}
2009
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302010/*
2011 * if native DSD playback active
2012 */
2013bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2014{
2015 bool active = false;
2016 struct listnode *node = NULL;
2017 struct audio_usecase *uc = NULL;
2018 struct stream_out *curr_out = NULL;
2019
2020 list_for_each(node, &adev->usecase_list) {
2021 uc = node_to_item(node, struct audio_usecase, list);
2022 curr_out = (struct stream_out*) uc->stream.out;
2023
2024 if (curr_out && PCM_PLAYBACK == uc->type &&
2025 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2026 active = true;
2027 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302028 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302029 }
2030 }
2031 return active;
2032}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302033
2034static bool force_device_switch(struct audio_usecase *usecase)
2035{
2036 bool ret = false;
2037 bool is_it_true_mode = false;
2038
Zhou Song30f2c3e2018-02-08 14:02:15 +08002039 if (usecase->type == PCM_CAPTURE ||
2040 usecase->type == TRANSCODE_LOOPBACK) {
2041 return false;
2042 }
2043
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002044 if(usecase->stream.out == NULL) {
2045 ALOGE("%s: stream.out is NULL", __func__);
2046 return false;
2047 }
2048
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302049 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002050 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2051 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2052 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302053 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2054 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2055 (!is_it_true_mode && adev->native_playback_enabled)){
2056 ret = true;
2057 ALOGD("napb: time to toggle native mode");
2058 }
2059 }
2060
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302061 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302062 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2063 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002064 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302065 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302066 ALOGD("Force a2dp device switch to update new encoder config");
2067 ret = true;
2068 }
2069
Manish Dewangan671a4202017-08-18 17:30:46 +05302070 if (usecase->stream.out->stream_config_changed) {
2071 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2072 return true;
2073 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302074 return ret;
2075}
2076
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302077bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2078{
2079 bool ret=false;
2080 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2081 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2082 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2083 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2084 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2085 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2086 ret = true;
2087
2088 return ret;
2089}
2090
2091bool is_a2dp_device(snd_device_t out_snd_device)
2092{
2093 bool ret=false;
2094 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2095 ret = true;
2096
2097 return ret;
2098}
2099
2100bool is_bt_soc_on(struct audio_device *adev)
2101{
2102 struct mixer_ctl *ctl;
2103 char *mixer_ctl_name = "BT SOC status";
2104 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2105 bool bt_soc_status = true;
2106 if (!ctl) {
2107 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2108 __func__, mixer_ctl_name);
2109 /*This is to ensure we dont break targets which dont have the kernel change*/
2110 return true;
2111 }
2112 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2113 ALOGD("BT SOC status: %d",bt_soc_status);
2114 return bt_soc_status;
2115}
2116
2117int out_standby_l(struct audio_stream *stream);
2118
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002119int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002121 snd_device_t out_snd_device = SND_DEVICE_NONE;
2122 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002123 struct audio_usecase *usecase = NULL;
2124 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002125 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002126 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302127 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002128 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002129 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302131 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2132
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002133 usecase = get_usecase_from_list(adev, uc_id);
2134 if (usecase == NULL) {
2135 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2136 return -EINVAL;
2137 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002139 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002140 (usecase->type == VOIP_CALL) ||
2141 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302142 if(usecase->stream.out == NULL) {
2143 ALOGE("%s: stream.out is NULL", __func__);
2144 return -EINVAL;
2145 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002146 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002147 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002148 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002149 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302150 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
2151 if (usecase->stream.inout == NULL) {
2152 ALOGE("%s: stream.inout is NULL", __func__);
2153 return -EINVAL;
2154 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302155 stream_out.devices = usecase->stream.inout->out_config.devices;
2156 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2157 stream_out.format = usecase->stream.inout->out_config.format;
2158 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2159 out_snd_device = platform_get_output_snd_device(adev->platform,
2160 &stream_out);
2161 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302162 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002163 } else {
2164 /*
2165 * If the voice call is active, use the sound devices of voice call usecase
2166 * so that it would not result any device switch. All the usecases will
2167 * be switched to new device when select_devices() is called for voice call
2168 * usecase. This is to avoid switching devices for voice call when
2169 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002170 * choose voice call device only if the use case device is
2171 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002172 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002173 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002174 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002175 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002176 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2177 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302178 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2179 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002180 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002181 in_snd_device = vc_usecase->in_snd_device;
2182 out_snd_device = vc_usecase->out_snd_device;
2183 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002184 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002185 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002186 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002187 if ((voip_usecase != NULL) &&
2188 (usecase->type == PCM_PLAYBACK) &&
2189 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002190 out_snd_device_backend_match = platform_check_backends_match(
2191 voip_usecase->out_snd_device,
2192 platform_get_output_snd_device(
2193 adev->platform,
2194 usecase->stream.out));
2195 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002196 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002197 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2198 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002199 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002200 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002201 in_snd_device = voip_usecase->in_snd_device;
2202 out_snd_device = voip_usecase->out_snd_device;
2203 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002204 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002205 hfp_ucid = audio_extn_hfp_get_usecase();
2206 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002207 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002208 in_snd_device = hfp_usecase->in_snd_device;
2209 out_snd_device = hfp_usecase->out_snd_device;
2210 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002211 }
2212 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302213 if (usecase->stream.out == NULL) {
2214 ALOGE("%s: stream.out is NULL", __func__);
2215 return -EINVAL;
2216 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002217 usecase->devices = usecase->stream.out->devices;
2218 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002219 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002220 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002221 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002222 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleiz3ca773f2018-10-12 15:49:35 +08002223 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002224 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2225
2226 if ((usecase->stream.out != NULL &&
2227 voip_usecase != NULL &&
2228 usecase->stream.out->usecase == voip_usecase->id) &&
2229 adev->active_input &&
kunleiz3ca773f2018-10-12 15:49:35 +08002230 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002231 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002232 select_devices(adev, adev->active_input->usecase);
2233 }
2234 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002235 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302236 if (usecase->stream.in == NULL) {
2237 ALOGE("%s: stream.in is NULL", __func__);
2238 return -EINVAL;
2239 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002240 usecase->devices = usecase->stream.in->device;
2241 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002242 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002243 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002244 if (adev->active_input &&
2245 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302246 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002247 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2248 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2249 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2250 out_device = voip_usecase->stream.out->devices;
2251 else if (adev->primary_output && !adev->primary_output->standby)
2252 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002253 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002254 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2255 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002256 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002257 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002258 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002259 }
2260 }
2261
2262 if (out_snd_device == usecase->out_snd_device &&
2263 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302264
2265 if (!force_device_switch(usecase))
2266 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002267 }
2268
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302269 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
2270 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
2271 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2272 return 0;
2273 }
2274
sangwoobc677242013-08-08 16:53:43 +09002275 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07002276 out_snd_device, platform_get_snd_device_name(out_snd_device),
2277 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002278
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279 /*
2280 * Limitation: While in call, to do a device switch we need to disable
2281 * and enable both RX and TX devices though one of them is same as current
2282 * device.
2283 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002284 if ((usecase->type == VOICE_CALL) &&
2285 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2286 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002287 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002288 }
2289
2290 if (((usecase->type == VOICE_CALL) ||
2291 (usecase->type == VOIP_CALL)) &&
2292 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2293 /* Disable sidetone only if voice/voip call already exists */
2294 if (voice_is_call_state_active(adev) ||
2295 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002296 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002297
2298 /* Disable aanc only if voice call exists */
2299 if (voice_is_call_state_active(adev))
2300 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002301 }
2302
Zhou Songc66eb7e2017-08-08 18:29:07 +08002303 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302304 (!audio_extn_a2dp_is_ready())) {
2305 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002306 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302307 }
2308
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002309 /* Disable current sound devices */
2310 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002311 disable_audio_route(adev, usecase);
2312 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313 }
2314
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002315 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002316 disable_audio_route(adev, usecase);
2317 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002318 }
2319
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002320 /* Applicable only on the targets that has external modem.
2321 * New device information should be sent to modem before enabling
2322 * the devices to reduce in-call device switch time.
2323 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002324 if ((usecase->type == VOICE_CALL) &&
2325 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2326 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002327 status = platform_switch_voice_call_enable_device_config(adev->platform,
2328 out_snd_device,
2329 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002330 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002331
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002332 /* Enable new sound devices */
2333 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002334 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302335 if (platform_check_codec_asrc_support(adev->platform))
2336 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002337 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002338 }
2339
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002340 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302341 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002342 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002343 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002344
Avinash Vaish71a8b972014-07-24 15:36:33 +05302345 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002346 status = platform_switch_voice_call_device_post(adev->platform,
2347 out_snd_device,
2348 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302349 enable_audio_route_for_voice_usecases(adev, usecase);
2350 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002351
sangwoo170731f2013-06-08 15:36:36 +09002352 usecase->in_snd_device = in_snd_device;
2353 usecase->out_snd_device = out_snd_device;
2354
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302355 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2356 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302357 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002358 if ((24 == usecase->stream.out->bit_width) &&
2359 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2360 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2361 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2362 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2363 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2364 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2365 /*
2366 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2367 * configured device sample rate, if not update the COPP rate to be equal to the
2368 * device sample rate, else open COPP at stream sample rate
2369 */
2370 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2371 usecase->stream.out->sample_rate,
2372 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302373 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2374 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002375 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2376 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2377 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2378 }
Weiyin Jiang619761e2019-07-08 16:13:16 +08002379 }
2380 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002381
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002382 /* If input stream is already running then effect needs to be
2383 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002384 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2385 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002386 check_and_enable_effect(adev);
2387
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002388 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002389 /* Enable aanc only if voice call exists */
2390 if (voice_is_call_state_active(adev))
2391 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2392
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002393 /* Enable sidetone only if other voice/voip call already exists */
2394 if (voice_is_call_state_active(adev) ||
2395 voice_extn_compress_voip_is_started(adev))
2396 voice_set_sidetone(adev, out_snd_device, true);
2397 }
2398
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002399 /* Applicable only on the targets that has external modem.
2400 * Enable device command should be sent to modem only after
2401 * enabling voice call mixer controls
2402 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002403 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002404 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2405 out_snd_device,
2406 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302407
2408 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2409
2410 if (usecase->type == VOIP_CALL) {
2411 if (adev->active_input != NULL &&
2412 !adev->active_input->standby) {
2413 if (is_bt_soc_on(adev) == false){
2414 ALOGD("BT SCO MIC disconnected while in connection");
2415 if (adev->active_input->pcm != NULL)
2416 pcm_stop(adev->active_input->pcm);
2417 }
2418 }
2419 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2420 && usecase->stream.out->started) {
2421 if (is_bt_soc_on(adev) == false) {
2422 ALOGD("BT SCO/A2DP disconnected while in connection");
2423 out_standby_l(&usecase->stream.out->stream.common);
2424 }
2425 }
2426 } else if ((usecase->stream.out != NULL) &&
2427 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2428 usecase->stream.out->started) {
2429 if (is_bt_soc_on(adev) == false) {
2430 ALOGD("BT SCO/A2dp disconnected while in connection");
2431 out_standby_l(&usecase->stream.out->stream.common);
2432 }
2433 }
2434 }
2435
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302436 ALOGD("%s: done",__func__);
2437
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438 return status;
2439}
2440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441static int stop_input_stream(struct stream_in *in)
2442{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302443 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002444 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +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;
2452
Eric Laurent994a6932013-07-17 11:51:42 -07002453 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002454 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455 uc_info = get_usecase_from_list(adev, in->usecase);
2456 if (uc_info == NULL) {
2457 ALOGE("%s: Could not find the usecase (%d) in the list",
2458 __func__, in->usecase);
2459 return -EINVAL;
2460 }
2461
Derek Chencdd17c72014-11-24 12:39:14 -08002462 if (uc_info->in_snd_device != SND_DEVICE_NONE) {
2463 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2464 ALOGE("%s: failed to stop ext hw plugin", __func__);
2465 }
2466
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002467 /* Close in-call recording streams */
2468 voice_check_and_stop_incall_rec_usecase(adev, in);
2469
Eric Laurent150dbfe2013-02-27 14:31:02 -08002470 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002471 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002472
2473 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002474 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002476 list_remove(&uc_info->list);
2477 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002479 adev->active_input = get_next_active_input(adev);
Vatsal Buchaa1358992018-11-14 13:25:08 +05302480 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002481 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482 return ret;
2483}
2484
2485int start_input_stream(struct stream_in *in)
2486{
2487 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002488 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302490
2491 if (in == NULL) {
2492 ALOGE("%s: stream_in ptr is NULL", __func__);
2493 return -EINVAL;
2494 }
2495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002497 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002498 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499
Mingming Yin2664a5b2015-09-03 10:53:11 -07002500 if (get_usecase_from_list(adev, usecase) == NULL)
2501 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302502 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2503 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002504
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302505 if (CARD_STATUS_OFFLINE == in->card_status||
2506 CARD_STATUS_OFFLINE == adev->card_status) {
2507 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302508 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302509 goto error_config;
2510 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302511
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302512 if (audio_is_bluetooth_sco_device(in->device)) {
2513 if (!adev->bt_sco_on) {
2514 ALOGE("%s: SCO profile is not ready, return error", __func__);
2515 ret = -EIO;
2516 goto error_config;
2517 }
2518 }
2519
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002520 /* Check if source matches incall recording usecase criteria */
2521 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2522 if (ret)
2523 goto error_config;
2524 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002525 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2526
2527 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2528 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2529 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002530 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002531 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002532
Eric Laurentb23d5282013-05-14 15:27:20 -07002533 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534 if (in->pcm_device_id < 0) {
2535 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2536 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002537 ret = -EINVAL;
2538 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002540
2541 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002543
2544 if (!uc_info) {
2545 ret = -ENOMEM;
2546 goto error_config;
2547 }
2548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 uc_info->id = in->usecase;
2550 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002551 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002552 uc_info->devices = in->device;
2553 uc_info->in_snd_device = SND_DEVICE_NONE;
2554 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002556 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302557 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2558 adev->perf_lock_opts,
2559 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002560 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561
Derek Chencdd17c72014-11-24 12:39:14 -08002562 if (uc_info->in_snd_device != SND_DEVICE_NONE) {
2563 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2564 ALOGE("%s: failed to start ext hw plugin", __func__);
2565 }
2566
Haynes Mathew George16081042017-05-31 17:16:49 -07002567 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302568 ret = audio_extn_cin_start_input_stream(in);
2569 if (ret)
2570 goto error_open;
2571 else
2572 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002573 }
2574
Haynes Mathew George16081042017-05-31 17:16:49 -07002575 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002576 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002577 ALOGE("%s: pcm stream not ready", __func__);
2578 goto error_open;
2579 }
2580 ret = pcm_start(in->pcm);
2581 if (ret < 0) {
2582 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2583 goto error_open;
2584 }
2585 } else {
2586 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2587 unsigned int pcm_open_retry_count = 0;
2588
2589 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2590 flags |= PCM_MMAP | PCM_NOIRQ;
2591 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2592 } else if (in->realtime) {
2593 flags |= PCM_MMAP | PCM_NOIRQ;
2594 }
2595
Garmond Leunge2433c32017-09-28 21:51:22 -07002596 if (audio_extn_ffv_get_stream() == in) {
2597 ALOGD("%s: ffv stream, update pcm config", __func__);
2598 audio_extn_ffv_update_pcm_config(&config);
2599 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002600 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2601 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2602
2603 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002604 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002605 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002606 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002607 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05302608 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
2609 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2610 adev->card_status = CARD_STATUS_OFFLINE;
2611 in->card_status = CARD_STATUS_OFFLINE;
2612 ret = -EIO;
2613 goto error_open;
2614 }
2615
Haynes Mathew George16081042017-05-31 17:16:49 -07002616 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2617 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2618 if (in->pcm != NULL) {
2619 pcm_close(in->pcm);
2620 in->pcm = NULL;
2621 }
2622 if (pcm_open_retry_count-- == 0) {
2623 ret = -EIO;
2624 goto error_open;
2625 }
2626 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2627 continue;
2628 }
2629 break;
2630 }
2631
2632 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002633 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002634 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002635 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002636 if (ret < 0) {
2637 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2638 pcm_close(in->pcm);
2639 in->pcm = NULL;
2640 goto error_open;
2641 }
2642 register_in_stream(in);
2643 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002644 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002645 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002646 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002647 if (ret < 0) {
2648 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002649 pcm_close(in->pcm);
2650 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002651 goto error_open;
2652 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002653 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002654 }
2655
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002656 check_and_enable_effect(adev);
2657
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302658done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302659 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002660 ALOGD("%s: exit", __func__);
Vatsal Buchaa1358992018-11-14 13:25:08 +05302661 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002662 return ret;
2663
2664error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302665 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002667error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302668 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302669 /*
2670 * sleep 50ms to allow sufficient time for kernel
2671 * drivers to recover incases like SSR.
2672 */
2673 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002674 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchaa1358992018-11-14 13:25:08 +05302675 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002676 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677}
2678
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002679void lock_input_stream(struct stream_in *in)
2680{
2681 pthread_mutex_lock(&in->pre_lock);
2682 pthread_mutex_lock(&in->lock);
2683 pthread_mutex_unlock(&in->pre_lock);
2684}
2685
2686void lock_output_stream(struct stream_out *out)
2687{
2688 pthread_mutex_lock(&out->pre_lock);
2689 pthread_mutex_lock(&out->lock);
2690 pthread_mutex_unlock(&out->pre_lock);
2691}
2692
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002693/* must be called with out->lock locked */
2694static int send_offload_cmd_l(struct stream_out* out, int command)
2695{
2696 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2697
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002698 if (!cmd) {
2699 ALOGE("failed to allocate mem for command 0x%x", command);
2700 return -ENOMEM;
2701 }
2702
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002703 ALOGVV("%s %d", __func__, command);
2704
2705 cmd->cmd = command;
2706 list_add_tail(&out->offload_cmd_list, &cmd->node);
2707 pthread_cond_signal(&out->offload_cond);
2708 return 0;
2709}
2710
2711/* must be called iwth out->lock locked */
2712static void stop_compressed_output_l(struct stream_out *out)
2713{
2714 out->offload_state = OFFLOAD_STATE_IDLE;
2715 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002716 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002717 if (out->compr != NULL) {
2718 compress_stop(out->compr);
2719 while (out->offload_thread_blocked) {
2720 pthread_cond_wait(&out->cond, &out->lock);
2721 }
2722 }
2723}
2724
Varun Balaraje49253e2017-07-06 19:48:56 +05302725bool is_interactive_usecase(audio_usecase_t uc_id)
2726{
2727 unsigned int i;
2728 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2729 if (uc_id == interactive_usecases[i])
2730 return true;
2731 }
2732 return false;
2733}
2734
2735static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2736{
2737 audio_usecase_t ret_uc = USECASE_INVALID;
2738 unsigned int intract_uc_index;
2739 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2740
2741 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2742 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2743 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2744 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2745 ret_uc = interactive_usecases[intract_uc_index];
2746 break;
2747 }
2748 }
2749
2750 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2751 return ret_uc;
2752}
2753
2754static void free_interactive_usecase(struct audio_device *adev,
2755 audio_usecase_t uc_id)
2756{
2757 unsigned int interact_uc_index;
2758 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2759
2760 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2761 if (interactive_usecases[interact_uc_index] == uc_id) {
2762 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2763 break;
2764 }
2765 }
2766 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2767}
2768
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002769bool is_offload_usecase(audio_usecase_t uc_id)
2770{
2771 unsigned int i;
2772 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2773 if (uc_id == offload_usecases[i])
2774 return true;
2775 }
2776 return false;
2777}
2778
Dhananjay Kumarac341582017-02-23 23:42:25 +05302779static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002780{
vivek mehta446c3962015-09-14 10:57:35 -07002781 audio_usecase_t ret_uc = USECASE_INVALID;
2782 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002783 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002784 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302785 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002786 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2787 else
2788 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002789
vivek mehta446c3962015-09-14 10:57:35 -07002790 pthread_mutex_lock(&adev->lock);
2791 if (get_usecase_from_list(adev, ret_uc) != NULL)
2792 ret_uc = USECASE_INVALID;
2793 pthread_mutex_unlock(&adev->lock);
2794
2795 return ret_uc;
2796 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002797
2798 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002799 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2800 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2801 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2802 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002803 break;
2804 }
2805 }
vivek mehta446c3962015-09-14 10:57:35 -07002806
2807 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2808 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002809}
2810
2811static void free_offload_usecase(struct audio_device *adev,
2812 audio_usecase_t uc_id)
2813{
vivek mehta446c3962015-09-14 10:57:35 -07002814 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002815 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002816
2817 if (!adev->multi_offload_enable)
2818 return;
2819
2820 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2821 if (offload_usecases[offload_uc_index] == uc_id) {
2822 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002823 break;
2824 }
2825 }
2826 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2827}
2828
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002829static void *offload_thread_loop(void *context)
2830{
2831 struct stream_out *out = (struct stream_out *) context;
2832 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002833 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002834
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002835 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2836 set_sched_policy(0, SP_FOREGROUND);
2837 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2838
2839 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002840 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002841 for (;;) {
2842 struct offload_cmd *cmd = NULL;
2843 stream_callback_event_t event;
2844 bool send_callback = false;
2845
2846 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2847 __func__, list_empty(&out->offload_cmd_list),
2848 out->offload_state);
2849 if (list_empty(&out->offload_cmd_list)) {
2850 ALOGV("%s SLEEPING", __func__);
2851 pthread_cond_wait(&out->offload_cond, &out->lock);
2852 ALOGV("%s RUNNING", __func__);
2853 continue;
2854 }
2855
2856 item = list_head(&out->offload_cmd_list);
2857 cmd = node_to_item(item, struct offload_cmd, node);
2858 list_remove(item);
2859
2860 ALOGVV("%s STATE %d CMD %d out->compr %p",
2861 __func__, out->offload_state, cmd->cmd, out->compr);
2862
2863 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2864 free(cmd);
2865 break;
2866 }
2867
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002868 // allow OFFLOAD_CMD_ERROR reporting during standby
2869 // this is needed to handle failures during compress_open
2870 // Note however that on a pause timeout, the stream is closed
2871 // and no offload usecase will be active. Therefore this
2872 // special case is needed for compress_open failures alone
2873 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2874 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002875 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002876 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002877 pthread_cond_signal(&out->cond);
2878 continue;
2879 }
2880 out->offload_thread_blocked = true;
2881 pthread_mutex_unlock(&out->lock);
2882 send_callback = false;
2883 switch(cmd->cmd) {
2884 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002885 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002886 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002887 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002888 send_callback = true;
2889 event = STREAM_CBK_EVENT_WRITE_READY;
2890 break;
2891 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002892 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302893 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002894 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302895 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002896 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302897 if (ret < 0)
2898 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302899 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302900 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002901 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002902 else
2903 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002904 if (-ENETRESET != ret && !(-EINTR == ret &&
2905 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302906 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302907 pthread_mutex_lock(&out->lock);
2908 out->send_new_metadata = 1;
2909 out->send_next_track_params = true;
2910 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302911 event = STREAM_CBK_EVENT_DRAIN_READY;
2912 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2913 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302914 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002915 break;
2916 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002917 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002918 ret = compress_drain(out->compr);
2919 ALOGD("copl(%p):out of compress_drain", out);
2920 // EINTR check avoids drain interruption due to SSR
2921 if (-ENETRESET != ret && !(-EINTR == ret &&
2922 CARD_STATUS_OFFLINE == out->card_status)) {
2923 send_callback = true;
2924 event = STREAM_CBK_EVENT_DRAIN_READY;
2925 } else
2926 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002927 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302928 case OFFLOAD_CMD_ERROR:
2929 ALOGD("copl(%p): sending error callback to AF", out);
2930 send_callback = true;
2931 event = STREAM_CBK_EVENT_ERROR;
2932 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002933 default:
2934 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2935 break;
2936 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002937 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002938 out->offload_thread_blocked = false;
2939 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002940 if (send_callback && out->client_callback) {
2941 ALOGVV("%s: sending client_callback event %d", __func__, event);
2942 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002943 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002944 free(cmd);
2945 }
2946
2947 pthread_cond_signal(&out->cond);
2948 while (!list_empty(&out->offload_cmd_list)) {
2949 item = list_head(&out->offload_cmd_list);
2950 list_remove(item);
2951 free(node_to_item(item, struct offload_cmd, node));
2952 }
2953 pthread_mutex_unlock(&out->lock);
2954
2955 return NULL;
2956}
2957
2958static int create_offload_callback_thread(struct stream_out *out)
2959{
2960 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2961 list_init(&out->offload_cmd_list);
2962 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2963 offload_thread_loop, out);
2964 return 0;
2965}
2966
2967static int destroy_offload_callback_thread(struct stream_out *out)
2968{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002969 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002970 stop_compressed_output_l(out);
2971 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2972
2973 pthread_mutex_unlock(&out->lock);
2974 pthread_join(out->offload_thread, (void **) NULL);
2975 pthread_cond_destroy(&out->offload_cond);
2976
2977 return 0;
2978}
2979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980static int stop_output_stream(struct stream_out *out)
2981{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302982 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983 struct audio_usecase *uc_info;
2984 struct audio_device *adev = out->dev;
2985
Eric Laurent994a6932013-07-17 11:51:42 -07002986 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002987 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002988 uc_info = get_usecase_from_list(adev, out->usecase);
2989 if (uc_info == NULL) {
2990 ALOGE("%s: Could not find the usecase (%d) in the list",
2991 __func__, out->usecase);
2992 return -EINVAL;
2993 }
2994
Derek Chencdd17c72014-11-24 12:39:14 -08002995 if (uc_info->out_snd_device != SND_DEVICE_NONE) {
2996 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2997 ALOGE("%s: failed to stop ext hw plugin", __func__);
2998 }
2999
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003000 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303001 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003002 if (adev->visualizer_stop_output != NULL)
3003 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003004
3005 audio_extn_dts_remove_state_notifier_node(out->usecase);
3006
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003007 if (adev->offload_effects_stop_output != NULL)
3008 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
3009 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003010
Arun Mirpuridbef0c72018-09-12 18:36:10 -07003011 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3012 out->usecase == USECASE_INCALL_MUSIC_UPLINK2)
Arun Mirpurief53ce52018-09-11 18:00:09 -07003013 voice_set_device_mute_flag(adev, false);
3014
Eric Laurent150dbfe2013-02-27 14:31:02 -08003015 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003016 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003017
3018 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003019 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003021 if (is_offload_usecase(out->usecase)) {
3022 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3023 adev->dsp_bit_width_enforce_mode,
3024 false);
3025 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003026 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3027 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3028 false);
3029
3030 if (ret != 0)
3031 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3032 /* default service interval was successfully updated,
3033 reopen USB backend with new service interval */
3034 ret = 0;
3035 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003036
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003037 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303038 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003039 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303040 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003041 ALOGV("Disable passthrough , reset mixer to pcm");
3042 /* NO_PASSTHROUGH */
3043 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003044 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003045 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3046 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003047
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303048 /* Must be called after removing the usecase from list */
3049 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303050 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303051
Manish Dewangan21a850a2017-08-14 12:03:55 +05303052 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003053 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3054 if (ret < 0)
3055 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3056 }
3057
Garmond Leung5fd0b552018-04-17 11:56:12 -07003058 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003059 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060 return ret;
3061}
3062
3063int start_output_stream(struct stream_out *out)
3064{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066 struct audio_usecase *uc_info;
3067 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003068 char mixer_ctl_name[128];
3069 struct mixer_ctl *ctl = NULL;
3070 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303071 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003072
Haynes Mathew George380745d2017-10-04 15:27:45 -07003073 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003074 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3075 ret = -EINVAL;
3076 goto error_config;
3077 }
3078
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303079 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
3080 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
3081 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303082
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303083 if (CARD_STATUS_OFFLINE == out->card_status ||
3084 CARD_STATUS_OFFLINE == adev->card_status) {
3085 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303086 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303087 goto error_config;
3088 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303089
Arun Mirpuridbef0c72018-09-12 18:36:10 -07003090 //Update incall music usecase to reflect correct voice session
3091 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3092 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3093 if (ret != 0) {
3094 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3095 __func__, ret);
3096 goto error_config;
3097 }
3098 }
3099
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303100 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
3101 if (!audio_extn_a2dp_is_ready()) {
3102 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303103 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303104 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303105 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3106 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3107 ret = -EAGAIN;
3108 goto error_config;
3109 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303110 }
3111 }
3112 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303113 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3114 if (!adev->bt_sco_on) {
3115 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3116 //combo usecase just by pass a2dp
3117 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3118 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3119 } else {
3120 ALOGE("%s: SCO profile is not ready, return error", __func__);
3121 ret = -EAGAIN;
3122 goto error_config;
3123 }
3124 }
3125 }
3126
Eric Laurentb23d5282013-05-14 15:27:20 -07003127 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128 if (out->pcm_device_id < 0) {
3129 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3130 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003131 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003132 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133 }
3134
3135 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003136
3137 if (!uc_info) {
3138 ret = -ENOMEM;
3139 goto error_config;
3140 }
3141
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142 uc_info->id = out->usecase;
3143 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003144 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003145 uc_info->devices = out->devices;
3146 uc_info->in_snd_device = SND_DEVICE_NONE;
3147 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003148
3149 /* This must be called before adding this usecase to the list */
3150 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3151 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3152 /* USB backend is not reopened immediately.
3153 This is eventually done as part of select_devices */
3154 }
3155
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003156 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003157
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303158 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3159 adev->perf_lock_opts,
3160 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303161
3162 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303163 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303164 if (audio_extn_passthru_is_enabled() &&
3165 audio_extn_passthru_is_passthrough_stream(out)) {
3166 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303167 }
3168 }
3169
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303170 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3171 (!audio_extn_a2dp_is_ready())) {
3172 if (!a2dp_combo) {
3173 check_a2dp_restore_l(adev, out, false);
3174 } else {
3175 audio_devices_t dev = out->devices;
3176 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3177 select_devices(adev, out->usecase);
3178 out->devices = dev;
3179 }
3180 } else {
3181 select_devices(adev, out->usecase);
3182 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003183
Arun Mirpuridbef0c72018-09-12 18:36:10 -07003184 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3185 out->usecase == USECASE_INCALL_MUSIC_UPLINK2)
Arun Mirpurief53ce52018-09-11 18:00:09 -07003186 voice_set_device_mute_flag(adev, true);
3187
Derek Chencdd17c72014-11-24 12:39:14 -08003188 if (uc_info->out_snd_device != SND_DEVICE_NONE) {
3189 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3190 ALOGE("%s: failed to start ext hw plugin", __func__);
3191 }
3192
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003193 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3194 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003195
3196 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuriebe78a72018-10-04 18:23:46 -07003197 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003198 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3199 ALOGE("%s: pcm stream not ready", __func__);
3200 goto error_open;
3201 }
3202 ret = pcm_start(out->pcm);
3203 if (ret < 0) {
3204 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3205 goto error_open;
3206 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07003207 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003208 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003209 unsigned int flags = PCM_OUT;
3210 unsigned int pcm_open_retry_count = 0;
3211 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3212 flags |= PCM_MMAP | PCM_NOIRQ;
3213 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003214 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003215 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003216 } else
3217 flags |= PCM_MONOTONIC;
3218
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003219 if ((adev->vr_audio_mode_enabled) &&
3220 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3221 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3222 "PCM_Dev %d Topology", out->pcm_device_id);
3223 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3224 if (!ctl) {
3225 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3226 __func__, mixer_ctl_name);
3227 } else {
3228 //if success use ULLPP
3229 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3230 __func__, mixer_ctl_name, out->pcm_device_id);
3231 //There is a still a possibility that some sessions
3232 // that request for FAST|RAW when 3D audio is active
3233 //can go through ULLPP. Ideally we expects apps to
3234 //listen to audio focus and stop concurrent playback
3235 //Also, we will look for mode flag (voice_in_communication)
3236 //before enabling the realtime flag.
3237 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3238 }
3239 }
3240
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003241 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003242 ATRACE_BEGIN("pcm_open");
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003243 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3244 flags, &out->config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003245 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05303246 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
3247 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3248 out->card_status = CARD_STATUS_OFFLINE;
3249 adev->card_status = CARD_STATUS_OFFLINE;
3250 ret = -EIO;
3251 goto error_open;
3252 }
3253
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003254 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3255 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3256 if (out->pcm != NULL) {
3257 pcm_close(out->pcm);
3258 out->pcm = NULL;
3259 }
3260 if (pcm_open_retry_count-- == 0) {
3261 ret = -EIO;
3262 goto error_open;
3263 }
3264 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3265 continue;
3266 }
3267 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003268 }
Surendar Karka5a18a7a2018-04-26 11:28:38 +05303269 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3270 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003271
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003272 ALOGV("%s: pcm_prepare", __func__);
3273 if (pcm_is_ready(out->pcm)) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003274 ATRACE_BEGIN("pcm_prepare");
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003275 ret = pcm_prepare(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003276 ATRACE_END();
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003277 if (ret < 0) {
3278 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3279 pcm_close(out->pcm);
3280 out->pcm = NULL;
3281 goto error_open;
3282 }
3283 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08003284 // apply volume for voip playback after path is set up
3285 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3286 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003287 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003288 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303289 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003290 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3291 adev->dsp_bit_width_enforce_mode,
3292 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003294 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003295 out->compr = compress_open(adev->snd_card,
3296 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003297 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003298 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05303299 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
3300 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3301 adev->card_status = CARD_STATUS_OFFLINE;
3302 out->card_status = CARD_STATUS_OFFLINE;
3303 ret = -EIO;
3304 goto error_open;
3305 }
3306
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003307 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003308 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003309 compress_close(out->compr);
3310 out->compr = NULL;
3311 ret = -EIO;
3312 goto error_open;
3313 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303314 /* compress_open sends params of the track, so reset the flag here */
3315 out->is_compr_metadata_avail = false;
3316
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003317 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003318 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003319
Fred Oh3f43e742015-03-04 18:42:34 -08003320 /* Since small bufs uses blocking writes, a write will be blocked
3321 for the default max poll time (20s) in the event of an SSR.
3322 Reduce the poll time to observe and deal with SSR faster.
3323 */
Ashish Jain5106d362016-05-11 19:23:33 +05303324 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003325 compress_set_max_poll_wait(out->compr, 1000);
3326 }
3327
Manish Dewangan69426c82017-01-30 17:35:36 +05303328 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303329 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303330
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003331 audio_extn_dts_create_state_notifier_node(out->usecase);
3332 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3333 popcount(out->channel_mask),
3334 out->playback_started);
3335
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003336#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303337 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003338 audio_extn_dolby_send_ddp_endp_params(adev);
3339#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303340 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3341 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003342 if (adev->visualizer_start_output != NULL)
3343 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3344 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303345 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003346 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003347 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003349
3350 if (ret == 0) {
3351 register_out_stream(out);
3352 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003353 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3354 ALOGE("%s: pcm stream not ready", __func__);
3355 goto error_open;
3356 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003357 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003358 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003359 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003360 if (ret < 0)
3361 goto error_open;
3362 }
3363 }
3364
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303365 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003366 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003367
Manish Dewangan21a850a2017-08-14 12:03:55 +05303368 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003369 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003370 if (ret < 0)
3371 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3372 }
3373
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003374 // consider a scenario where on pause lower layers are tear down.
3375 // so on resume, swap mixer control need to be sent only when
3376 // backend is active, hence rather than sending from enable device
3377 // sending it from start of streamtream
3378
3379 platform_set_swap_channels(adev, true);
3380
Haynes Mathew George380745d2017-10-04 15:27:45 -07003381 ATRACE_END();
Vatsal Buchaa1358992018-11-14 13:25:08 +05303382 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003383 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003384error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303385 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003387error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303388 /*
3389 * sleep 50ms to allow sufficient time for kernel
3390 * drivers to recover incases like SSR.
3391 */
3392 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003393 ATRACE_END();
Vatsal Buchaa1358992018-11-14 13:25:08 +05303394 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003395 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396}
3397
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003398static int check_input_parameters(uint32_t sample_rate,
3399 audio_format_t format,
3400 int channel_count)
3401{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003402 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303404 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3405 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3406 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003407 !voice_extn_compress_voip_is_format_supported(format) &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003408 !audio_extn_compr_cap_format_supported(format))
3409 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003410
3411 switch (channel_count) {
3412 case 1:
3413 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303414 case 3:
3415 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003416 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003417 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003418 break;
3419 default:
3420 ret = -EINVAL;
3421 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422
3423 switch (sample_rate) {
3424 case 8000:
3425 case 11025:
3426 case 12000:
3427 case 16000:
3428 case 22050:
3429 case 24000:
3430 case 32000:
3431 case 44100:
3432 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003433 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303434 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003435 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303436 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003437 break;
3438 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003439 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440 }
3441
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003442 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003443}
3444
Naresh Tanniru04f71882018-06-26 17:46:22 +05303445
3446/** Add a value in a list if not already present.
3447 * @return true if value was successfully inserted or already present,
3448 * false if the list is full and does not contain the value.
3449 */
3450static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3451 for (size_t i = 0; i < list_length; i++) {
3452 if (list[i] == value) return true; // value is already present
3453 if (list[i] == 0) { // no values in this slot
3454 list[i] = value;
3455 return true; // value inserted
3456 }
3457 }
3458 return false; // could not insert value
3459}
3460
3461/** Add channel_mask in supported_channel_masks if not already present.
3462 * @return true if channel_mask was successfully inserted or already present,
3463 * false if supported_channel_masks is full and does not contain channel_mask.
3464 */
3465static void register_channel_mask(audio_channel_mask_t channel_mask,
3466 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3467 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3468 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3469}
3470
3471/** Add format in supported_formats if not already present.
3472 * @return true if format was successfully inserted or already present,
3473 * false if supported_formats is full and does not contain format.
3474 */
3475static void register_format(audio_format_t format,
3476 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3477 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3478 "%s: stream can not declare supporting its format %x", __func__, format);
3479}
3480/** Add sample_rate in supported_sample_rates if not already present.
3481 * @return true if sample_rate was successfully inserted or already present,
3482 * false if supported_sample_rates is full and does not contain sample_rate.
3483 */
3484static void register_sample_rate(uint32_t sample_rate,
3485 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3486 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3487 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3488}
3489
Karthikeyan Mani35531922018-11-07 15:44:13 -08003490static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3491{
3492 uint32_t high = num1, low = num2, temp = 0;
3493
3494 if (!num1 || !num2)
3495 return 0;
3496
3497 if (num1 < num2) {
3498 high = num2;
3499 low = num1;
3500 }
3501
3502 while (low != 0) {
3503 temp = low;
3504 low = high % low;
3505 high = temp;
3506 }
3507 return (num1 * num2)/high;
3508}
3509
3510static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3511{
3512 uint32_t remainder = 0;
3513
3514 if (!multiplier)
3515 return num;
3516
3517 remainder = num % multiplier;
3518 if (remainder)
3519 num += (multiplier - remainder);
3520
3521 return num;
3522}
3523
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524static size_t get_input_buffer_size(uint32_t sample_rate,
3525 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003526 int channel_count,
3527 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528{
3529 size_t size = 0;
Karthikeyan Mani35531922018-11-07 15:44:13 -08003530 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003532 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3533 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003535 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003536 if (is_low_latency)
3537 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303538
Karthikeyan Mani35531922018-11-07 15:44:13 -08003539 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
3540 size *= bytes_per_period_sample;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003541
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003542 /* make sure the size is multiple of 32 bytes
3543 * At 48 kHz mono 16-bit PCM:
3544 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3545 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Mani35531922018-11-07 15:44:13 -08003546 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003547 */
Karthikeyan Mani35531922018-11-07 15:44:13 -08003548 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003549
3550 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551}
3552
Ashish Jain058165c2016-09-28 23:18:48 +05303553static size_t get_output_period_size(uint32_t sample_rate,
3554 audio_format_t format,
3555 int channel_count,
3556 int duration /*in millisecs*/)
3557{
3558 size_t size = 0;
3559 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3560
3561 if ((duration == 0) || (sample_rate == 0) ||
3562 (bytes_per_sample == 0) || (channel_count == 0)) {
3563 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3564 bytes_per_sample, channel_count);
3565 return -EINVAL;
3566 }
3567
3568 size = (sample_rate *
3569 duration *
3570 bytes_per_sample *
3571 channel_count) / 1000;
3572 /*
3573 * To have same PCM samples for all channels, the buffer size requires to
3574 * be multiple of (number of channels * bytes per sample)
3575 * For writes to succeed, the buffer must be written at address which is multiple of 32
3576 */
3577 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3578
3579 return (size/(channel_count * bytes_per_sample));
3580}
3581
Zhou Song48453a02018-01-10 17:50:59 +08003582static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303583{
3584 uint64_t actual_frames_rendered = 0;
3585 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3586
3587 /* This adjustment accounts for buffering after app processor.
3588 * It is based on estimated DSP latency per use case, rather than exact.
3589 */
3590 int64_t platform_latency = platform_render_latency(out->usecase) *
3591 out->sample_rate / 1000000LL;
3592
Zhou Song48453a02018-01-10 17:50:59 +08003593 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303594 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3595 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3596 * hence only estimate.
3597 */
3598 int64_t signed_frames = out->written - kernel_buffer_size;
3599
3600 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3601
Zhou Song48453a02018-01-10 17:50:59 +08003602 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303603 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003604 if (timestamp != NULL )
3605 *timestamp = out->writeAt;
3606 } else if (timestamp != NULL) {
3607 clock_gettime(CLOCK_MONOTONIC, timestamp);
3608 }
3609 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303610
3611 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3612 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3613 (long long int)out->written, (int)kernel_buffer_size,
3614 audio_bytes_per_sample(out->compr_config.codec->format),
3615 popcount(out->channel_mask));
3616
3617 return actual_frames_rendered;
3618}
3619
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3621{
3622 struct stream_out *out = (struct stream_out *)stream;
3623
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003624 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625}
3626
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003627static int out_set_sample_rate(struct audio_stream *stream __unused,
3628 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629{
3630 return -ENOSYS;
3631}
3632
3633static size_t out_get_buffer_size(const struct audio_stream *stream)
3634{
3635 struct stream_out *out = (struct stream_out *)stream;
3636
Varun Balaraje49253e2017-07-06 19:48:56 +05303637 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303638 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303639 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303640 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3641 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3642 else
3643 return out->compr_config.fragment_size;
3644 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003645 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003646 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3647 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 +05303648 else if (is_offload_usecase(out->usecase) &&
3649 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303650 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003651
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003652 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003653 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654}
3655
3656static uint32_t out_get_channels(const struct audio_stream *stream)
3657{
3658 struct stream_out *out = (struct stream_out *)stream;
3659
3660 return out->channel_mask;
3661}
3662
3663static audio_format_t out_get_format(const struct audio_stream *stream)
3664{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003665 struct stream_out *out = (struct stream_out *)stream;
3666
3667 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668}
3669
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003670static int out_set_format(struct audio_stream *stream __unused,
3671 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672{
3673 return -ENOSYS;
3674}
3675
3676static int out_standby(struct audio_stream *stream)
3677{
3678 struct stream_out *out = (struct stream_out *)stream;
3679 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003680 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003681
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303682 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3683 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003685 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003687 if (adev->adm_deregister_stream)
3688 adev->adm_deregister_stream(adev->adm_data, out->handle);
3689
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003690 if (is_offload_usecase(out->usecase))
3691 stop_compressed_output_l(out);
3692
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003693 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003695 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3696 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303697 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003698 pthread_mutex_unlock(&adev->lock);
3699 pthread_mutex_unlock(&out->lock);
3700 ALOGD("VOIP output entered standby");
3701 return 0;
3702 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003703 if (out->pcm) {
3704 pcm_close(out->pcm);
3705 out->pcm = NULL;
3706 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003707 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3708 do_stop = out->playback_started;
3709 out->playback_started = false;
3710 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003711 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003712 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303713 out->send_next_track_params = false;
3714 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003715 out->gapless_mdata.encoder_delay = 0;
3716 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003717 if (out->compr != NULL) {
3718 compress_close(out->compr);
3719 out->compr = NULL;
3720 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003721 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003722 if (do_stop) {
3723 stop_output_stream(out);
3724 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003725 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726 }
3727 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303728 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729 return 0;
3730}
3731
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303732static int out_on_error(struct audio_stream *stream)
3733{
3734 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003735 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303736
3737 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003738 // always send CMD_ERROR for offload streams, this
3739 // is needed e.g. when SSR happens within compress_open
3740 // since the stream is active, offload_callback_thread is also active.
3741 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3742 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003743 }
3744 pthread_mutex_unlock(&out->lock);
3745
3746 status = out_standby(&out->stream.common);
3747
3748 lock_output_stream(out);
3749 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003750 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303751 }
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05303752
3753 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
3754 ALOGD("Setting previous card status if offline");
3755 out->prev_card_status_offline = true;
3756 }
3757
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303758 pthread_mutex_unlock(&out->lock);
3759
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003760 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303761}
3762
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303763/*
3764 *standby implementation without locks, assumes that the callee already
3765 *has taken adev and out lock.
3766 */
3767int out_standby_l(struct audio_stream *stream)
3768{
3769 struct stream_out *out = (struct stream_out *)stream;
3770 struct audio_device *adev = out->dev;
3771
3772 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3773 stream, out->usecase, use_case_table[out->usecase]);
3774
3775 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003776 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303777 if (adev->adm_deregister_stream)
3778 adev->adm_deregister_stream(adev->adm_data, out->handle);
3779
3780 if (is_offload_usecase(out->usecase))
3781 stop_compressed_output_l(out);
3782
3783 out->standby = true;
3784 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3785 voice_extn_compress_voip_close_output_stream(stream);
3786 out->started = 0;
3787 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003788 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303789 return 0;
3790 } else if (!is_offload_usecase(out->usecase)) {
3791 if (out->pcm) {
3792 pcm_close(out->pcm);
3793 out->pcm = NULL;
3794 }
3795 } else {
3796 ALOGD("copl(%p):standby", out);
3797 out->send_next_track_params = false;
3798 out->is_compr_metadata_avail = false;
3799 out->gapless_mdata.encoder_delay = 0;
3800 out->gapless_mdata.encoder_padding = 0;
3801 if (out->compr != NULL) {
3802 compress_close(out->compr);
3803 out->compr = NULL;
3804 }
3805 }
3806 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003807 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303808 }
3809 ALOGD("%s: exit", __func__);
3810 return 0;
3811}
3812
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003813static int out_dump(const struct audio_stream *stream __unused,
3814 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003815{
3816 return 0;
3817}
3818
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003819static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3820{
3821 int ret = 0;
3822 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003823
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003824 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003825 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003826 return -EINVAL;
3827 }
3828
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303829 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003830
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003831 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3832 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303833 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003834 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003835 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3836 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303837 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003838 }
3839
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003840 ALOGV("%s new encoder delay %u and padding %u", __func__,
3841 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3842
3843 return 0;
3844}
3845
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003846static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3847{
3848 return out == adev->primary_output || out == adev->voice_tx_output;
3849}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003850
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303851// note: this call is safe only if the stream_cb is
3852// removed first in close_output_stream (as is done now).
3853static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3854{
3855 if (!stream || !parms)
3856 return;
3857
3858 struct stream_out *out = (struct stream_out *)stream;
3859 struct audio_device *adev = out->dev;
3860
3861 card_status_t status;
3862 int card;
3863 if (parse_snd_card_status(parms, &card, &status) < 0)
3864 return;
3865
3866 pthread_mutex_lock(&adev->lock);
3867 bool valid_cb = (card == adev->snd_card);
3868 pthread_mutex_unlock(&adev->lock);
3869
3870 if (!valid_cb)
3871 return;
3872
3873 lock_output_stream(out);
3874 if (out->card_status != status)
3875 out->card_status = status;
3876 pthread_mutex_unlock(&out->lock);
3877
3878 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3879 use_case_table[out->usecase],
3880 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3881
Aditya Bavanari9aa0b922019-02-05 17:44:57 +05303882 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303883 out_on_error(stream);
Aditya Bavanari9aa0b922019-02-05 17:44:57 +05303884 if (voice_is_call_state_active(adev) &&
3885 out == adev->primary_output) {
3886 ALOGD("%s: SSR/PDR occurred, end all calls", __func__);
3887 pthread_mutex_lock(&adev->lock);
3888 voice_stop_call(adev);
3889 adev->mode = AUDIO_MODE_NORMAL;
3890 pthread_mutex_unlock(&adev->lock);
3891 }
3892 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303893 return;
3894}
3895
Kevin Rocardfce19002017-08-07 19:21:36 -07003896static int get_alive_usb_card(struct str_parms* parms) {
3897 int card;
3898 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
3899 !audio_extn_usb_alive(card)) {
3900 return card;
3901 }
3902 return -ENODEV;
3903}
3904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003905static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3906{
3907 struct stream_out *out = (struct stream_out *)stream;
3908 struct audio_device *adev = out->dev;
3909 struct str_parms *parms;
3910 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003911 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303912 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003913 bool reconfig = false;
3914 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915
sangwoobc677242013-08-08 16:53:43 +09003916 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003917 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303919 if (!parms)
3920 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003921 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3922 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003924 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003925 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003926
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003927 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003928 * When HDMI cable is unplugged the music playback is paused and
3929 * the policy manager sends routing=0. But the audioflinger continues
3930 * to write data until standby time (3sec). As the HDMI core is
3931 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003932 * Avoid this by routing audio to speaker until standby.
3933 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003934 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3935 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303936 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003937 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3938 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003939 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303940 /*
3941 * When A2DP is disconnected the
3942 * music playback is paused and the policy manager sends routing=0
3943 * But the audioflingercontinues to write data until standby time
3944 * (3sec). As BT is turned off, the write gets blocked.
3945 * Avoid this by routing audio to speaker until standby.
3946 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003947 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07003948 (val == AUDIO_DEVICE_NONE) &&
3949 !audio_extn_a2dp_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303950 val = AUDIO_DEVICE_OUT_SPEAKER;
3951 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05303952 /*
3953 * When USB headset is disconnected the music platback paused
3954 * and the policy manager send routing=0. But if the USB is connected
3955 * back before the standby time, AFE is not closed and opened
3956 * when USB is connected back. So routing to speker will guarantee
3957 * AFE reconfiguration and AFE will be opend once USB is connected again
3958 */
3959 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
3960 (val == AUDIO_DEVICE_NONE) &&
3961 !audio_extn_usb_connected(parms)) {
3962 val = AUDIO_DEVICE_OUT_SPEAKER;
3963 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303964 /* To avoid a2dp to sco overlapping / BT device improper state
3965 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303966 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303967 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3968 if (!audio_extn_a2dp_is_ready()) {
3969 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3970 //combo usecase just by pass a2dp
3971 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303972 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303973 } else {
3974 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3975 /* update device to a2dp and don't route as BT returned error
3976 * However it is still possible a2dp routing called because
3977 * of current active device disconnection (like wired headset)
3978 */
3979 out->devices = val;
3980 pthread_mutex_unlock(&out->lock);
3981 pthread_mutex_unlock(&adev->lock);
3982 goto error;
3983 }
3984 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303985 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003986
3987 audio_devices_t new_dev = val;
3988
3989 // Workaround: If routing to an non existing usb device, fail gracefully
3990 // The routing request will otherwise block during 10 second
3991 int card;
3992 if (audio_is_usb_out_device(new_dev) &&
3993 (card = get_alive_usb_card(parms)) >= 0) {
3994
3995 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
3996 pthread_mutex_unlock(&adev->lock);
3997 pthread_mutex_unlock(&out->lock);
3998 ret = -ENOSYS;
3999 goto routing_fail;
4000 }
4001
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004002 /*
4003 * select_devices() call below switches all the usecases on the same
4004 * backend to the new device. Refer to check_usecases_codec_backend() in
4005 * the select_devices(). But how do we undo this?
4006 *
4007 * For example, music playback is active on headset (deep-buffer usecase)
4008 * and if we go to ringtones and select a ringtone, low-latency usecase
4009 * will be started on headset+speaker. As we can't enable headset+speaker
4010 * and headset devices at the same time, select_devices() switches the music
4011 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4012 * So when the ringtone playback is completed, how do we undo the same?
4013 *
4014 * We are relying on the out_set_parameters() call on deep-buffer output,
4015 * once the ringtone playback is ended.
4016 * NOTE: We should not check if the current devices are same as new devices.
4017 * Because select_devices() must be called to switch back the music
4018 * playback to headset.
4019 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004020 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004021 audio_devices_t new_dev = val;
4022 bool same_dev = out->devices == new_dev;
4023 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004024
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004025 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004026 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004027 if (adev->mode == AUDIO_MODE_IN_CALL) {
4028 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004029 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4030 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4031 audio_extn_usb_set_service_interval(true /*playback*/,
4032 service_interval,
4033 &reconfig);
4034 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4035 }
4036 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004037 }
4038 } else {
4039 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004040 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004041 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004042 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004043
4044 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004045 if (!same_dev) {
4046 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304047 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4048 adev->perf_lock_opts,
4049 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004050 if (adev->adm_on_routing_change)
4051 adev->adm_on_routing_change(adev->adm_data,
4052 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004053 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304054 if (!bypass_a2dp) {
4055 select_devices(adev, out->usecase);
4056 } else {
4057 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
4058 select_devices(adev, out->usecase);
4059 out->devices = new_dev;
4060 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004061
4062 if (!same_dev) {
4063 // on device switch force swap, lower functions will make sure
4064 // to check if swap is allowed or not.
4065 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304066 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004067 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304068 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4069 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08004070 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304071 pthread_mutex_lock(&out->compr_mute_lock);
4072 out->a2dp_compress_mute = false;
4073 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4074 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004075 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4076 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304077 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004078 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004079 }
4080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004081 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004082 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004083 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004084 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004085
4086 if (out == adev->primary_output) {
4087 pthread_mutex_lock(&adev->lock);
4088 audio_extn_set_parameters(adev, parms);
4089 pthread_mutex_unlock(&adev->lock);
4090 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004091 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004092 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004093 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004094
4095 audio_extn_dts_create_state_notifier_node(out->usecase);
4096 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4097 popcount(out->channel_mask),
4098 out->playback_started);
4099
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004100 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004101 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004102
Surendar Karka5a18a7a2018-04-26 11:28:38 +05304103 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4104 sizeof(value));
4105 if (err >= 0) {
4106 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4107 audio_extn_send_dual_mono_mixing_coefficients(out);
4108 }
4109
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304110 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4111 if (err >= 0) {
4112 strlcpy(out->profile, value, sizeof(out->profile));
4113 ALOGV("updating stream profile with value '%s'", out->profile);
4114 lock_output_stream(out);
4115 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4116 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004117 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304118 out->sample_rate, out->bit_width,
4119 out->channel_mask, out->profile,
4120 &out->app_type_cfg);
4121 pthread_mutex_unlock(&out->lock);
4122 }
4123
Alexy Joseph98988832017-01-13 14:56:59 -08004124 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004125 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4126 // and vendor.audio.hal.output.suspend.supported is set to true
4127 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004128 //check suspend parameter only for low latency and if the property
4129 //is enabled
4130 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4131 ALOGI("%s: got suspend_playback %s", __func__, value);
4132 lock_output_stream(out);
4133 if (!strncmp(value, "false", 5)) {
4134 //suspend_playback=false is supposed to set QOS value back to 75%
4135 //the mixer control sent with value Enable will achieve that
4136 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4137 } else if (!strncmp (value, "true", 4)) {
4138 //suspend_playback=true is supposed to remove QOS value
4139 //resetting the mixer control will set the default value
4140 //for the mixer control which is Disable and this removes the QOS vote
4141 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4142 } else {
4143 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4144 " got %s", __func__, value);
4145 ret = -1;
4146 }
4147
4148 if (ret != 0) {
4149 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4150 __func__, out->pm_qos_mixer_path, ret);
4151 }
4152
4153 pthread_mutex_unlock(&out->lock);
4154 }
4155 }
4156 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004157 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304158error:
Eric Laurent994a6932013-07-17 11:51:42 -07004159 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004160 return ret;
4161}
4162
Ramjee Singhacef98f2019-06-28 11:01:25 +05304163#if ANDROID_PLATFORM_SDK_VERSION >= 29
4164static int in_set_microphone_direction(const struct audio_stream_in *stream,
4165 audio_microphone_direction_t dir) {
4166 int ret_val = -ENOSYS;
4167 (void)stream;
4168 (void)dir;
4169 ALOGV("---- in_set_microphone_direction()");
4170 return ret_val;
4171}
4172
4173static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
4174 int ret_val = -ENOSYS;
4175 (void)zoom;
4176 (void)stream;
4177 ALOGV("---- in_set_microphone_field_dimension()");
4178 return ret_val;
4179}
4180#endif
4181
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004182static bool stream_get_parameter_channels(struct str_parms *query,
4183 struct str_parms *reply,
4184 audio_channel_mask_t *supported_channel_masks) {
4185 int ret = -1;
4186 char value[512];
4187 bool first = true;
4188 size_t i, j;
4189
4190 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4191 ret = 0;
4192 value[0] = '\0';
4193 i = 0;
4194 while (supported_channel_masks[i] != 0) {
4195 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4196 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4197 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304198 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004199
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304200 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004201 first = false;
4202 break;
4203 }
4204 }
4205 i++;
4206 }
4207 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4208 }
4209 return ret == 0;
4210}
4211
4212static bool stream_get_parameter_formats(struct str_parms *query,
4213 struct str_parms *reply,
4214 audio_format_t *supported_formats) {
4215 int ret = -1;
4216 char value[256];
4217 size_t i, j;
4218 bool first = true;
4219
4220 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4221 ret = 0;
4222 value[0] = '\0';
4223 i = 0;
4224 while (supported_formats[i] != 0) {
4225 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4226 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4227 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304228 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004229 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304230 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004231 first = false;
4232 break;
4233 }
4234 }
4235 i++;
4236 }
4237 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4238 }
4239 return ret == 0;
4240}
4241
4242static bool stream_get_parameter_rates(struct str_parms *query,
4243 struct str_parms *reply,
4244 uint32_t *supported_sample_rates) {
4245
4246 int i;
4247 char value[256];
4248 int ret = -1;
4249 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4250 ret = 0;
4251 value[0] = '\0';
4252 i=0;
4253 int cursor = 0;
4254 while (supported_sample_rates[i]) {
4255 int avail = sizeof(value) - cursor;
4256 ret = snprintf(value + cursor, avail, "%s%d",
4257 cursor > 0 ? "|" : "",
4258 supported_sample_rates[i]);
4259 if (ret < 0 || ret >= avail) {
4260 // if cursor is at the last element of the array
4261 // overwrite with \0 is duplicate work as
4262 // snprintf already put a \0 in place.
4263 // else
4264 // we had space to write the '|' at value[cursor]
4265 // (which will be overwritten) or no space to fill
4266 // the first element (=> cursor == 0)
4267 value[cursor] = '\0';
4268 break;
4269 }
4270 cursor += ret;
4271 ++i;
4272 }
4273 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4274 value);
4275 }
4276 return ret >= 0;
4277}
4278
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004279static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4280{
4281 struct stream_out *out = (struct stream_out *)stream;
4282 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004283 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004284 char value[256];
4285 struct str_parms *reply = str_parms_create();
4286 size_t i, j;
4287 int ret;
4288 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004289
4290 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004291 if (reply) {
4292 str_parms_destroy(reply);
4293 }
4294 if (query) {
4295 str_parms_destroy(query);
4296 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004297 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4298 return NULL;
4299 }
4300
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004301 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4303 if (ret >= 0) {
4304 value[0] = '\0';
4305 i = 0;
4306 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004307 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4308 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004309 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004310 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004311 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004312 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313 first = false;
4314 break;
4315 }
4316 }
4317 i++;
4318 }
4319 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4320 str = str_parms_to_str(reply);
4321 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004322 voice_extn_out_get_parameters(out, query, reply);
4323 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004324 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004325
Alexy Joseph62142aa2015-11-16 15:10:34 -08004326
4327 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4328 if (ret >= 0) {
4329 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304330 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4331 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004332 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304333 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004334 } else {
4335 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304336 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004337 }
4338 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004339 if (str)
4340 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004341 str = str_parms_to_str(reply);
4342 }
4343
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004344 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4345 if (ret >= 0) {
4346 value[0] = '\0';
4347 i = 0;
4348 first = true;
4349 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004350 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4351 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004352 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004353 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004354 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004355 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004356 first = false;
4357 break;
4358 }
4359 }
4360 i++;
4361 }
4362 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004363 if (str)
4364 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004365 str = str_parms_to_str(reply);
4366 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004367
4368 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4369 if (ret >= 0) {
4370 value[0] = '\0';
4371 i = 0;
4372 first = true;
4373 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004374 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4375 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004376 if (!first) {
4377 strlcat(value, "|", sizeof(value));
4378 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004379 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004380 first = false;
4381 break;
4382 }
4383 }
4384 i++;
4385 }
4386 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4387 if (str)
4388 free(str);
4389 str = str_parms_to_str(reply);
4390 }
4391
Alexy Joseph98988832017-01-13 14:56:59 -08004392 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4393 //only low latency track supports suspend_resume
4394 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004395 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004396 if (str)
4397 free(str);
4398 str = str_parms_to_str(reply);
4399 }
4400
4401
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004402 str_parms_destroy(query);
4403 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004404 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004405 return str;
4406}
4407
4408static uint32_t out_get_latency(const struct audio_stream_out *stream)
4409{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004410 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004411 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004412 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004413
Alexy Josephaa54c872014-12-03 02:46:47 -08004414 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304415 lock_output_stream(out);
4416 latency = audio_extn_utils_compress_get_dsp_latency(out);
4417 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004418 } else if ((out->realtime) ||
4419 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004420 // since the buffer won't be filled up faster than realtime,
4421 // return a smaller number
4422 if (out->config.rate)
4423 period_ms = (out->af_period_multiplier * out->config.period_size *
4424 1000) / (out->config.rate);
4425 else
4426 period_ms = 0;
4427 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004428 } else {
4429 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004430 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004431 }
4432
yidongh0515e042017-07-06 15:00:34 +08004433 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004434 latency += audio_extn_a2dp_get_encoder_latency();
4435
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304436 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004437 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004438}
4439
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304440static float AmpToDb(float amplification)
4441{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304442 float db = DSD_VOLUME_MIN_DB;
4443 if (amplification > 0) {
4444 db = 20 * log10(amplification);
4445 if(db < DSD_VOLUME_MIN_DB)
4446 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304447 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304448 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304449}
4450
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004451static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4452 float right)
4453{
4454 struct stream_out *out = (struct stream_out *)stream;
4455 long volume = 0;
4456 char mixer_ctl_name[128] = "";
4457 struct audio_device *adev = out->dev;
4458 struct mixer_ctl *ctl = NULL;
4459 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4460 PCM_PLAYBACK);
4461
4462 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4463 "Playback %d Volume", pcm_device_id);
4464 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4465 if (!ctl) {
4466 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4467 __func__, mixer_ctl_name);
4468 return -EINVAL;
4469 }
4470 if (left != right)
4471 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4472 __func__, left, right);
4473 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4474 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4475 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4476 __func__, mixer_ctl_name, volume);
4477 return -EINVAL;
4478 }
4479 return 0;
4480}
4481
4482
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304483static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4484 float right)
4485{
4486 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304487 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304488 char mixer_ctl_name[128];
4489 struct audio_device *adev = out->dev;
4490 struct mixer_ctl *ctl;
4491 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4492 PCM_PLAYBACK);
4493
4494 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4495 "Compress Playback %d Volume", pcm_device_id);
4496 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4497 if (!ctl) {
4498 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4499 __func__, mixer_ctl_name);
4500 return -EINVAL;
4501 }
4502 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4503 __func__, mixer_ctl_name, left, right);
4504 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4505 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4506 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4507
4508 return 0;
4509}
4510
Zhou Song2b8f28f2017-09-11 10:51:38 +08004511static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4512 float right)
4513{
4514 struct stream_out *out = (struct stream_out *)stream;
4515 char mixer_ctl_name[] = "App Type Gain";
4516 struct audio_device *adev = out->dev;
4517 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304518 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004519
4520 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4521 if (!ctl) {
4522 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4523 __func__, mixer_ctl_name);
4524 return -EINVAL;
4525 }
4526
4527 set_values[0] = 0; //0: Rx Session 1:Tx Session
4528 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304529 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4530 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004531
4532 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4533 return 0;
4534}
4535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004536static int out_set_volume(struct audio_stream_out *stream, float left,
4537 float right)
4538{
Eric Laurenta9024de2013-04-04 09:19:12 -07004539 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004540 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304541 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004542
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004543 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
4544
Eric Laurenta9024de2013-04-04 09:19:12 -07004545 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4546 /* only take left channel into account: the API is for stereo anyway */
4547 out->muted = (left == 0.0f);
4548 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004549 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304550 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004551 /*
4552 * Set mute or umute on HDMI passthrough stream.
4553 * Only take left channel into account.
4554 * Mute is 0 and unmute 1
4555 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304556 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304557 } else if (out->format == AUDIO_FORMAT_DSD){
4558 char mixer_ctl_name[128] = "DSD Volume";
4559 struct audio_device *adev = out->dev;
4560 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4561
4562 if (!ctl) {
4563 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4564 __func__, mixer_ctl_name);
4565 return -EINVAL;
4566 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304567 volume[0] = (long)(AmpToDb(left));
4568 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304569 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4570 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004571 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304572 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004573 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304574 if (!out->a2dp_compress_mute)
4575 ret = out_set_compr_volume(stream, left, right);
4576 out->volume_l = left;
4577 out->volume_r = right;
4578 pthread_mutex_unlock(&out->compr_mute_lock);
4579 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004580 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004581 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004582 if (!out->standby)
4583 ret = out_set_voip_volume(stream, left, right);
4584 out->volume_l = left;
4585 out->volume_r = right;
4586 return ret;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004587 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4588 ALOGV("%s: MMAP set volume called", __func__);
4589 if (!out->standby)
4590 ret = out_set_mmap_volume(stream, left, right);
4591 out->volume_l = left;
4592 out->volume_r = right;
4593 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004594 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004595
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004596 return -ENOSYS;
4597}
4598
Zhou Songc9672822017-08-16 16:01:39 +08004599static void update_frames_written(struct stream_out *out, size_t bytes)
4600{
4601 size_t bpf = 0;
4602
4603 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4604 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4605 bpf = 1;
4606 else if (!is_offload_usecase(out->usecase))
4607 bpf = audio_bytes_per_sample(out->format) *
4608 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004609
4610 pthread_mutex_lock(&out->position_query_lock);
4611 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004612 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004613 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4614 }
4615 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004616}
4617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004618static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4619 size_t bytes)
4620{
4621 struct stream_out *out = (struct stream_out *)stream;
4622 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004623 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304624 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004625 const size_t frame_size = audio_stream_out_frame_size(stream);
4626 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05304627 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004628
Haynes Mathew George380745d2017-10-04 15:27:45 -07004629 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004630 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304631
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304632 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004633
Dhananjay Kumarac341582017-02-23 23:42:25 +05304634 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304635 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304636 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4637 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004638 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304639 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304640 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304641 ALOGD(" %s: sound card is not active/SSR state", __func__);
4642 ret= -EIO;
4643 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304644 }
4645 }
4646
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304647 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304648 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304649 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304650 goto exit;
4651 }
4652
Haynes Mathew George16081042017-05-31 17:16:49 -07004653 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4654 ret = -EINVAL;
4655 goto exit;
4656 }
4657
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304658 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4659 !out->is_iec61937_info_available) {
4660
4661 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4662 out->is_iec61937_info_available = true;
4663 } else if (audio_extn_passthru_is_enabled()) {
4664 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304665 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304666
4667 if((out->format == AUDIO_FORMAT_DTS) ||
4668 (out->format == AUDIO_FORMAT_DTS_HD)) {
4669 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4670 buffer, bytes);
4671 if (ret) {
4672 if (ret != -ENOSYS) {
4673 out->is_iec61937_info_available = false;
4674 ALOGD("iec61937 transmission info not yet updated retry");
4675 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304676 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304677 /* if stream has started and after that there is
4678 * stream config change (iec transmission config)
4679 * then trigger select_device to update backend configuration.
4680 */
4681 out->stream_config_changed = true;
4682 pthread_mutex_lock(&adev->lock);
4683 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304684 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4685 ret = -EINVAL;
4686 goto exit;
4687 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304688 pthread_mutex_unlock(&adev->lock);
4689 out->stream_config_changed = false;
4690 out->is_iec61937_info_available = true;
4691 }
4692 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304693
Garmond Leung317cbf12017-09-13 16:20:50 -07004694 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304695 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4696 (out->is_iec61937_info_available == true)) {
4697 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4698 ret = -EINVAL;
4699 goto exit;
4700 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304701 }
4702 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304703
4704 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4705 (audio_extn_a2dp_is_suspended())) {
4706 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4707 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304708 ret = -EIO;
4709 goto exit;
4710 }
4711 }
4712 }
4713
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004714 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004715 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004716 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004717 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4718 ret = voice_extn_compress_voip_start_output_stream(out);
4719 else
4720 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004721 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004722 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004723 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004724 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004725 goto exit;
4726 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304727 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004728 if (last_known_cal_step != -1) {
4729 ALOGD("%s: retry previous failed cal level set", __func__);
4730 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304731 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004732 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304733
4734 if ((out->is_iec61937_info_available == true) &&
4735 (audio_extn_passthru_is_passthrough_stream(out))&&
4736 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4737 ret = -EINVAL;
4738 goto exit;
4739 }
Surendar Karka5a18a7a2018-04-26 11:28:38 +05304740 if (out->set_dual_mono)
4741 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004742 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004743
Ashish Jain81eb2a82015-05-13 10:52:34 +05304744 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004745 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304746 adev->is_channel_status_set = true;
4747 }
4748
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05304749 if ((adev->use_old_pspd_mix_ctrl == true) &&
4750 (out->pspd_coeff_sent == false)) {
4751 /*
4752 * Need to resend pspd coefficients after stream started for
4753 * older kernel version as it does not save the coefficients
4754 * and also stream has to be started for coeff to apply.
4755 */
4756 usecase = get_usecase_from_list(adev, out->usecase);
4757 if (usecase != NULL) {
4758 audio_extn_set_custom_mtmx_params(adev, usecase, true);
4759 out->pspd_coeff_sent = true;
4760 }
4761 }
4762
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004763 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004764 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004765 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004766 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004767 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4768 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304769 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4770 ALOGD("copl(%p):send next track params in gapless", out);
4771 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4772 out->send_next_track_params = false;
4773 out->is_compr_metadata_avail = false;
4774 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004775 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304776 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304777 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004778
Ashish Jain83a6cc22016-06-28 14:34:17 +05304779 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304780 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304781 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304782 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004783 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304784 return -EINVAL;
4785 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304786 audio_format_t dst_format = out->hal_op_format;
4787 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304788
4789 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4790 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4791
Ashish Jain83a6cc22016-06-28 14:34:17 +05304792 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304793 dst_format,
4794 buffer,
4795 src_format,
4796 frames);
4797
Ashish Jain83a6cc22016-06-28 14:34:17 +05304798 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304799 bytes_to_write);
4800
4801 /*Convert written bytes in audio flinger format*/
4802 if (ret > 0)
4803 ret = ((ret * format_to_bitwidth_table[out->format]) /
4804 format_to_bitwidth_table[dst_format]);
4805 }
4806 } else
4807 ret = compress_write(out->compr, buffer, bytes);
4808
Zhou Songc9672822017-08-16 16:01:39 +08004809 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4810 update_frames_written(out, bytes);
4811
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304812 if (ret < 0)
4813 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08004814 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304815 /*msg to cb thread only if non blocking write is enabled*/
4816 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304817 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004818 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304819 } else if (-ENETRESET == ret) {
4820 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304821 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304822 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304823 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004824 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304825 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004826 }
Ashish Jain5106d362016-05-11 19:23:33 +05304827
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304828 /* Call compr start only when non-zero bytes of data is there to be rendered */
4829 if (!out->playback_started && ret > 0) {
4830 int status = compress_start(out->compr);
4831 if (status < 0) {
4832 ret = status;
4833 ALOGE("%s: compr start failed with err %d", __func__, errno);
4834 goto exit;
4835 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004836 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004837 out->playback_started = 1;
4838 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004839
4840 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4841 popcount(out->channel_mask),
4842 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004843 }
4844 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004845 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004846 return ret;
4847 } else {
4848 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004849 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004850 if (out->muted)
4851 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004852 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
4853 __func__, frames, frame_size, bytes_to_write);
4854
Arun Mirpuridbef0c72018-09-12 18:36:10 -07004855 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4856 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004857 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4858 int16_t *src = (int16_t *)buffer;
4859 int16_t *dst = (int16_t *)buffer;
4860
4861 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
4862 out->format != AUDIO_FORMAT_PCM_16_BIT,
4863 "out_write called for incall music use case with wrong properties");
4864
4865 /*
4866 * FIXME: this can be removed once audio flinger mixer supports
4867 * mono output
4868 */
4869
4870 /*
4871 * Code below goes over each frame in the buffer and adds both
4872 * L and R samples and then divides by 2 to convert to mono
4873 */
4874 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
4875 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
4876 }
4877 bytes_to_write /= 2;
4878 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004879
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304880 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004881
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004882 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004883
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004884 if (out->config.rate)
4885 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4886 out->config.rate;
4887
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004888 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004889 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4890
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004891 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004892 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004893 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304894 out->convert_buffer != NULL) {
4895
4896 memcpy_by_audio_format(out->convert_buffer,
4897 out->hal_op_format,
4898 buffer,
4899 out->hal_ip_format,
4900 out->config.period_size * out->config.channels);
4901
4902 ret = pcm_write(out->pcm, out->convert_buffer,
4903 (out->config.period_size *
4904 out->config.channels *
4905 format_to_bitwidth_table[out->hal_op_format]));
4906 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304907 /*
4908 * To avoid underrun in DSP when the application is not pumping
4909 * data at required rate, check for the no. of bytes and ignore
4910 * pcm_write if it is less than actual buffer size.
4911 * It is a work around to a change in compress VOIP driver.
4912 */
4913 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4914 bytes < (out->config.period_size * out->config.channels *
4915 audio_bytes_per_sample(out->format))) {
4916 size_t voip_buf_size =
4917 out->config.period_size * out->config.channels *
4918 audio_bytes_per_sample(out->format);
4919 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4920 __func__, bytes, voip_buf_size);
4921 usleep(((uint64_t)voip_buf_size - bytes) *
4922 1000000 / audio_stream_out_frame_size(stream) /
4923 out_get_sample_rate(&out->stream.common));
4924 ret = 0;
4925 } else
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004926 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304927 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004928
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004929 release_out_focus(out);
4930
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304931 if (ret < 0)
4932 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004933 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304934 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004935 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004936 }
4937
4938exit:
Zhou Songc9672822017-08-16 16:01:39 +08004939 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304940 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304941 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304942 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004943 pthread_mutex_unlock(&out->lock);
4944
4945 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004946 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004947 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304948 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304949 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304950 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304951 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304952 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304953 out->standby = true;
4954 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304955 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304956 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4957 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4958 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004959
4960 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05304961 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004962 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004963 return ret;
4964 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004965 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004966 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004967 return bytes;
4968}
4969
4970static int out_get_render_position(const struct audio_stream_out *stream,
4971 uint32_t *dsp_frames)
4972{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004973 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004974
4975 if (dsp_frames == NULL)
4976 return -EINVAL;
4977
4978 *dsp_frames = 0;
4979 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004980 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304981
4982 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4983 * this operation and adev_close_output_stream(where out gets reset).
4984 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304985 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004986 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05304987 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004988 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304989 return 0;
4990 }
4991
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004992 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304993 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304994 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004995 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304996 if (ret < 0)
4997 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004998 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304999 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005000 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305001 if (-ENETRESET == ret) {
5002 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305003 out->card_status = CARD_STATUS_OFFLINE;
5004 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305005 } else if(ret < 0) {
5006 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305007 ret = -EINVAL;
5008 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305009 /*
5010 * Handle corner case where compress session is closed during SSR
5011 * and timestamp is queried
5012 */
5013 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305014 ret = -EINVAL;
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05305015 } else if (out->prev_card_status_offline) {
5016 ALOGE("ERROR: previously sound card was offline,return error");
5017 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305018 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305019 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005020 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305021 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305022 pthread_mutex_unlock(&out->lock);
5023 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005024 } else if (audio_is_linear_pcm(out->format)) {
5025 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005026 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005027 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005028 } else
5029 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005030}
5031
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005032static int out_add_audio_effect(const struct audio_stream *stream __unused,
5033 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005034{
5035 return 0;
5036}
5037
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005038static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5039 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005040{
5041 return 0;
5042}
5043
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005044static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5045 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005046{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305047 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005048}
5049
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005050static int out_get_presentation_position(const struct audio_stream_out *stream,
5051 uint64_t *frames, struct timespec *timestamp)
5052{
5053 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305054 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005055 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005056
Ashish Jain5106d362016-05-11 19:23:33 +05305057 /* below piece of code is not guarded against any lock because audioFliner serializes
5058 * this operation and adev_close_output_stream( where out gets reset).
5059 */
5060 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305061 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005062 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305063 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5064 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5065 return 0;
5066 }
5067
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005068 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005069
Ashish Jain5106d362016-05-11 19:23:33 +05305070 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5071 ret = compress_get_tstamp(out->compr, &dsp_frames,
5072 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005073 // Adjustment accounts for A2dp encoder latency with offload usecases
5074 // Note: Encoder latency is returned in ms.
5075 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5076 unsigned long offset =
5077 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5078 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5079 }
Ashish Jain5106d362016-05-11 19:23:33 +05305080 ALOGVV("%s rendered frames %ld sample_rate %d",
5081 __func__, dsp_frames, out->sample_rate);
5082 *frames = dsp_frames;
5083 if (ret < 0)
5084 ret = -errno;
5085 if (-ENETRESET == ret) {
5086 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305087 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305088 ret = -EINVAL;
5089 } else
5090 ret = 0;
5091 /* this is the best we can do */
5092 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005093 } else {
5094 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005095 unsigned int avail;
5096 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5097 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5098 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5099 // This adjustment accounts for buffering after app processor.
5100 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005101 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005102 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005103
Weiyin Jiangd4633762018-03-16 12:05:03 +08005104 // Adjustment accounts for A2dp encoder latency with non offload usecases
5105 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5106 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5107 signed_frames -=
5108 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5109 }
5110
5111 // It would be unusual for this value to be negative, but check just in case ...
5112 if (signed_frames >= 0) {
5113 *frames = signed_frames;
5114 ret = 0;
5115 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005116 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305117 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305118 *frames = out->written;
5119 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05305120 if (is_offload_usecase(out->usecase))
5121 ret = -EINVAL;
5122 else
5123 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005124 }
5125 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005126 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005127 return ret;
5128}
5129
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005130static int out_set_callback(struct audio_stream_out *stream,
5131 stream_callback_t callback, void *cookie)
5132{
5133 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005134 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005135
5136 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005137 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005138 out->client_callback = callback;
5139 out->client_cookie = cookie;
5140 if (out->adsp_hdlr_stream_handle) {
5141 ret = audio_extn_adsp_hdlr_stream_set_callback(
5142 out->adsp_hdlr_stream_handle,
5143 callback,
5144 cookie);
5145 if (ret)
5146 ALOGW("%s:adsp hdlr callback registration failed %d",
5147 __func__, ret);
5148 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005149 pthread_mutex_unlock(&out->lock);
5150 return 0;
5151}
5152
5153static int out_pause(struct audio_stream_out* stream)
5154{
5155 struct stream_out *out = (struct stream_out *)stream;
5156 int status = -ENOSYS;
5157 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005158 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005159 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005160 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005161 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305162 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305163 status = compress_pause(out->compr);
5164
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005165 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005166
Mingming Yin21854652016-04-13 11:54:02 -07005167 if (audio_extn_passthru_is_active()) {
5168 ALOGV("offload use case, pause passthru");
5169 audio_extn_passthru_on_pause(out);
5170 }
5171
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305172 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005173 audio_extn_dts_notify_playback_state(out->usecase, 0,
5174 out->sample_rate, popcount(out->channel_mask),
5175 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005176 }
5177 pthread_mutex_unlock(&out->lock);
5178 }
5179 return status;
5180}
5181
5182static int out_resume(struct audio_stream_out* stream)
5183{
5184 struct stream_out *out = (struct stream_out *)stream;
5185 int status = -ENOSYS;
5186 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005187 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005188 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005189 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005190 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005191 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305192 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305193 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005194 }
5195 if (!status) {
5196 out->offload_state = OFFLOAD_STATE_PLAYING;
5197 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305198 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005199 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5200 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005201 }
5202 pthread_mutex_unlock(&out->lock);
5203 }
5204 return status;
5205}
5206
5207static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5208{
5209 struct stream_out *out = (struct stream_out *)stream;
5210 int status = -ENOSYS;
5211 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005212 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005213 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005214 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5215 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5216 else
5217 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5218 pthread_mutex_unlock(&out->lock);
5219 }
5220 return status;
5221}
5222
5223static int out_flush(struct audio_stream_out* stream)
5224{
5225 struct stream_out *out = (struct stream_out *)stream;
5226 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005227 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005228 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005229 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005230 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5231 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005232 } else {
5233 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5234 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005235 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005236 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005237 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005238 return 0;
5239 }
5240 return -ENOSYS;
5241}
5242
Haynes Mathew George16081042017-05-31 17:16:49 -07005243static int out_stop(const struct audio_stream_out* stream)
5244{
5245 struct stream_out *out = (struct stream_out *)stream;
5246 struct audio_device *adev = out->dev;
5247 int ret = -ENOSYS;
5248
5249 ALOGV("%s", __func__);
5250 pthread_mutex_lock(&adev->lock);
5251 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5252 out->playback_started && out->pcm != NULL) {
5253 pcm_stop(out->pcm);
5254 ret = stop_output_stream(out);
5255 out->playback_started = false;
5256 }
5257 pthread_mutex_unlock(&adev->lock);
5258 return ret;
5259}
5260
5261static int out_start(const struct audio_stream_out* stream)
5262{
5263 struct stream_out *out = (struct stream_out *)stream;
5264 struct audio_device *adev = out->dev;
5265 int ret = -ENOSYS;
5266
5267 ALOGV("%s", __func__);
5268 pthread_mutex_lock(&adev->lock);
5269 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5270 !out->playback_started && out->pcm != NULL) {
5271 ret = start_output_stream(out);
5272 if (ret == 0) {
5273 out->playback_started = true;
5274 }
5275 }
5276 pthread_mutex_unlock(&adev->lock);
5277 return ret;
5278}
5279
5280/*
5281 * Modify config->period_count based on min_size_frames
5282 */
5283static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5284{
5285 int periodCountRequested = (min_size_frames + config->period_size - 1)
5286 / config->period_size;
5287 int periodCount = MMAP_PERIOD_COUNT_MIN;
5288
5289 ALOGV("%s original config.period_size = %d config.period_count = %d",
5290 __func__, config->period_size, config->period_count);
5291
5292 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5293 periodCount *= 2;
5294 }
5295 config->period_count = periodCount;
5296
5297 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5298}
5299
5300static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5301 int32_t min_size_frames,
5302 struct audio_mmap_buffer_info *info)
5303{
5304 struct stream_out *out = (struct stream_out *)stream;
5305 struct audio_device *adev = out->dev;
5306 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005307 unsigned int offset1 = 0;
5308 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005309 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005310 uint32_t mmap_size;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005311 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005312
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005313 ALOGD("%s", __func__);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305314 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005315 pthread_mutex_lock(&adev->lock);
5316
Sharad Sangle90e613f2018-05-04 16:15:38 +05305317 if (CARD_STATUS_OFFLINE == out->card_status ||
5318 CARD_STATUS_OFFLINE == adev->card_status) {
5319 ALOGW("out->card_status or adev->card_status offline, try again");
5320 ret = -EIO;
5321 goto exit;
5322 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005323 if (info == NULL || min_size_frames == 0) {
5324 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5325 ret = -EINVAL;
5326 goto exit;
5327 }
5328 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5329 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5330 ret = -ENOSYS;
5331 goto exit;
5332 }
5333 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5334 if (out->pcm_device_id < 0) {
5335 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5336 __func__, out->pcm_device_id, out->usecase);
5337 ret = -EINVAL;
5338 goto exit;
5339 }
5340
5341 adjust_mmap_period_count(&out->config, min_size_frames);
5342
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005343 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005344 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5345 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5346 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305347 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
5348 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5349 out->card_status = CARD_STATUS_OFFLINE;
5350 adev->card_status = CARD_STATUS_OFFLINE;
5351 ret = -EIO;
5352 goto exit;
5353 }
5354
Haynes Mathew George16081042017-05-31 17:16:49 -07005355 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5356 step = "open";
5357 ret = -ENODEV;
5358 goto exit;
5359 }
5360 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5361 if (ret < 0) {
5362 step = "begin";
5363 goto exit;
5364 }
5365 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005366 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005367 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005368 ret = platform_get_mmap_data_fd(adev->platform,
5369 out->pcm_device_id, 0 /*playback*/,
5370 &info->shared_memory_fd,
5371 &mmap_size);
5372 if (ret < 0) {
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005373 // Fall back to non exclusive mode
5374 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5375 } else {
5376 if (mmap_size < buffer_size) {
5377 step = "mmap";
5378 goto exit;
5379 }
5380 // FIXME: indicate exclusive mode support by returning a negative buffer size
5381 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005382 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005383 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07005384
5385 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5386 if (ret < 0) {
5387 step = "commit";
5388 goto exit;
5389 }
5390
5391 out->standby = false;
5392 ret = 0;
5393
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005394 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005395 __func__, info->shared_memory_address, info->buffer_size_frames);
5396
5397exit:
5398 if (ret != 0) {
5399 if (out->pcm == NULL) {
5400 ALOGE("%s: %s - %d", __func__, step, ret);
5401 } else {
5402 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5403 pcm_close(out->pcm);
5404 out->pcm = NULL;
5405 }
5406 }
5407 pthread_mutex_unlock(&adev->lock);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305408 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005409 return ret;
5410}
5411
5412static int out_get_mmap_position(const struct audio_stream_out *stream,
5413 struct audio_mmap_position *position)
5414{
5415 struct stream_out *out = (struct stream_out *)stream;
5416 ALOGVV("%s", __func__);
5417 if (position == NULL) {
5418 return -EINVAL;
5419 }
5420 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005421 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005422 return -ENOSYS;
5423 }
5424 if (out->pcm == NULL) {
5425 return -ENOSYS;
5426 }
5427
5428 struct timespec ts = { 0, 0 };
5429 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5430 if (ret < 0) {
5431 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5432 return ret;
5433 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005434 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005435 return 0;
5436}
5437
5438
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005439/** audio_stream_in implementation **/
5440static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5441{
5442 struct stream_in *in = (struct stream_in *)stream;
5443
5444 return in->config.rate;
5445}
5446
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005447static int in_set_sample_rate(struct audio_stream *stream __unused,
5448 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005449{
5450 return -ENOSYS;
5451}
5452
5453static size_t in_get_buffer_size(const struct audio_stream *stream)
5454{
5455 struct stream_in *in = (struct stream_in *)stream;
5456
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005457 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5458 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005459 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5460 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 -07005461 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5462 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305463 else if(audio_extn_cin_attached_usecase(in->usecase))
5464 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005465
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005466 return in->config.period_size * in->af_period_multiplier *
5467 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005468}
5469
5470static uint32_t in_get_channels(const struct audio_stream *stream)
5471{
5472 struct stream_in *in = (struct stream_in *)stream;
5473
5474 return in->channel_mask;
5475}
5476
5477static audio_format_t in_get_format(const struct audio_stream *stream)
5478{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005479 struct stream_in *in = (struct stream_in *)stream;
5480
5481 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005482}
5483
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005484static int in_set_format(struct audio_stream *stream __unused,
5485 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005486{
5487 return -ENOSYS;
5488}
5489
5490static int in_standby(struct audio_stream *stream)
5491{
5492 struct stream_in *in = (struct stream_in *)stream;
5493 struct audio_device *adev = in->dev;
5494 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305495 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5496 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005497 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305498
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005499 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005500 if (!in->standby && in->is_st_session) {
5501 ALOGD("%s: sound trigger pcm stop lab", __func__);
5502 audio_extn_sound_trigger_stop_lab(in);
5503 in->standby = 1;
5504 }
5505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005506 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005507 if (adev->adm_deregister_stream)
5508 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5509
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005510 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005511 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005512 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005513 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005514 voice_extn_compress_voip_close_input_stream(stream);
5515 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005516 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5517 do_stop = in->capture_started;
5518 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005519 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305520 if (audio_extn_cin_attached_usecase(in->usecase))
5521 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005522 }
5523
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005524 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005525 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005526 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005527 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005528 in->pcm = NULL;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005529 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005530
5531 if (do_stop)
5532 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005533 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005534 }
5535 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005536 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005537 return status;
5538}
5539
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005540static int in_dump(const struct audio_stream *stream __unused,
5541 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005542{
5543 return 0;
5544}
5545
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305546static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5547{
5548 if (!stream || !parms)
5549 return;
5550
5551 struct stream_in *in = (struct stream_in *)stream;
5552 struct audio_device *adev = in->dev;
5553
5554 card_status_t status;
5555 int card;
5556 if (parse_snd_card_status(parms, &card, &status) < 0)
5557 return;
5558
5559 pthread_mutex_lock(&adev->lock);
5560 bool valid_cb = (card == adev->snd_card);
5561 pthread_mutex_unlock(&adev->lock);
5562
5563 if (!valid_cb)
5564 return;
5565
5566 lock_input_stream(in);
5567 if (in->card_status != status)
5568 in->card_status = status;
5569 pthread_mutex_unlock(&in->lock);
5570
5571 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5572 use_case_table[in->usecase],
5573 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5574
5575 // a better solution would be to report error back to AF and let
5576 // it put the stream to standby
5577 if (status == CARD_STATUS_OFFLINE)
5578 in_standby(&in->stream.common);
5579
5580 return;
5581}
5582
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005583static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5584{
5585 struct stream_in *in = (struct stream_in *)stream;
5586 struct audio_device *adev = in->dev;
5587 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005588 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005589 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005590
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305591 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005592 parms = str_parms_create_str(kvpairs);
5593
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305594 if (!parms)
5595 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005596 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005597 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005598
5599 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5600 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005601 val = atoi(value);
5602 /* no audio source uses val == 0 */
5603 if ((in->source != val) && (val != 0)) {
5604 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005605 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5606 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5607 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005608 (in->config.rate == 8000 || in->config.rate == 16000 ||
5609 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005610 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005611 err = voice_extn_compress_voip_open_input_stream(in);
5612 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005613 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005614 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005615 }
5616 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005617 }
5618 }
5619
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005620 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5621 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005622 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005623 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5624
5625 // Workaround: If routing to an non existing usb device, fail gracefully
5626 // The routing request will otherwise block during 10 second
5627 int card;
5628 if (audio_is_usb_in_device(val) &&
5629 (card = get_alive_usb_card(parms)) >= 0) {
5630
5631 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5632 ret = -ENOSYS;
5633 } else {
5634
5635 in->device = val;
5636 /* If recording is in progress, change the tx device to new device */
5637 if (!in->standby && !in->is_st_session) {
5638 ALOGV("update input routing change");
5639 // inform adm before actual routing to prevent glitches.
5640 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005641 adev->adm_on_routing_change(adev->adm_data,
5642 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005643 ret = select_devices(adev, in->usecase);
5644 }
5645 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005646 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005647 }
5648 }
5649
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305650 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5651 if (err >= 0) {
5652 strlcpy(in->profile, value, sizeof(in->profile));
5653 ALOGV("updating stream profile with value '%s'", in->profile);
5654 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5655 &adev->streams_input_cfg_list,
5656 in->device, in->flags, in->format,
5657 in->sample_rate, in->bit_width,
5658 in->profile, &in->app_type_cfg);
5659 }
5660
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005661 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005662 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005663
5664 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305665error:
Eric Laurent994a6932013-07-17 11:51:42 -07005666 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005667 return ret;
5668}
5669
5670static char* in_get_parameters(const struct audio_stream *stream,
5671 const char *keys)
5672{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005673 struct stream_in *in = (struct stream_in *)stream;
5674 struct str_parms *query = str_parms_create_str(keys);
5675 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005676 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005677
5678 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005679 if (reply) {
5680 str_parms_destroy(reply);
5681 }
5682 if (query) {
5683 str_parms_destroy(query);
5684 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005685 ALOGE("in_get_parameters: failed to create query or reply");
5686 return NULL;
5687 }
5688
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005689 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005690
5691 voice_extn_in_get_parameters(in, query, reply);
5692
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005693 stream_get_parameter_channels(query, reply,
5694 &in->supported_channel_masks[0]);
5695 stream_get_parameter_formats(query, reply,
5696 &in->supported_formats[0]);
5697 stream_get_parameter_rates(query, reply,
5698 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005699 str = str_parms_to_str(reply);
5700 str_parms_destroy(query);
5701 str_parms_destroy(reply);
5702
5703 ALOGV("%s: exit: returns - %s", __func__, str);
5704 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005705}
5706
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005707static int in_set_gain(struct audio_stream_in *stream __unused,
5708 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005709{
5710 return 0;
5711}
5712
5713static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5714 size_t bytes)
5715{
5716 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305717
5718 if (in == NULL) {
5719 ALOGE("%s: stream_in ptr is NULL", __func__);
5720 return -EINVAL;
5721 }
5722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005723 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305724 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305725 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005726
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005727 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305728
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005729 if (in->is_st_session) {
5730 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5731 /* Read from sound trigger HAL */
5732 audio_extn_sound_trigger_read(in, buffer, bytes);
5733 pthread_mutex_unlock(&in->lock);
5734 return bytes;
5735 }
5736
Haynes Mathew George16081042017-05-31 17:16:49 -07005737 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5738 ret = -ENOSYS;
5739 goto exit;
5740 }
5741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005742 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005743 pthread_mutex_lock(&adev->lock);
5744 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5745 ret = voice_extn_compress_voip_start_input_stream(in);
5746 else
5747 ret = start_input_stream(in);
5748 pthread_mutex_unlock(&adev->lock);
5749 if (ret != 0) {
5750 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005751 }
5752 in->standby = 0;
5753 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005754
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005755 // what's the duration requested by the client?
5756 long ns = 0;
5757
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305758 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005759 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5760 in->config.rate;
5761
5762 request_in_focus(in, ns);
5763 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005764
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305765 if (audio_extn_cin_attached_usecase(in->usecase)) {
5766 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5767 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305768 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005769 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305770 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005771 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005772 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005773 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005774 } else if (audio_extn_ffv_get_stream() == in) {
5775 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305776 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005777 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305778 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5779 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5780 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5781 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305782 ret = -EINVAL;
5783 goto exit;
5784 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305785 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305786 ret = -errno;
5787 }
5788 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305789 /* bytes read is always set to bytes for non compress usecases */
5790 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005791 }
5792
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005793 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005794
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005795 /*
5796 * Instead of writing zeroes here, we could trust the hardware
5797 * to always provide zeroes when muted.
5798 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305799 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5800 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005801 memset(buffer, 0, bytes);
5802
5803exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005804 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305805 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005806 pthread_mutex_unlock(&in->lock);
5807
5808 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305809 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305810 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305811 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305812 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305813 in->standby = true;
5814 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305815 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5816 bytes_read = bytes;
5817 memset(buffer, 0, bytes);
5818 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005819 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005820 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305821 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305822 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005823 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305824 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005825}
5826
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005827static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005828{
5829 return 0;
5830}
5831
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005832static int add_remove_audio_effect(const struct audio_stream *stream,
5833 effect_handle_t effect,
5834 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005835{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005836 struct stream_in *in = (struct stream_in *)stream;
5837 int status = 0;
5838 effect_descriptor_t desc;
5839
5840 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005841 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5842
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005843 if (status != 0)
5844 return status;
5845
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005846 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005847 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08005848 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5849 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005850 in->enable_aec != enable &&
5851 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5852 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005853 if (!in->standby) {
5854 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5855 select_devices(in->dev, in->usecase);
5856 }
5857
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005858 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005859 if (in->enable_ns != enable &&
5860 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5861 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005862 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08005863 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5864 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005865 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5866 select_devices(in->dev, in->usecase);
5867 } else
5868 select_devices(in->dev, in->usecase);
5869 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005870 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005871 pthread_mutex_unlock(&in->dev->lock);
5872 pthread_mutex_unlock(&in->lock);
5873
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005874 return 0;
5875}
5876
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005877static int in_add_audio_effect(const struct audio_stream *stream,
5878 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005879{
Eric Laurent994a6932013-07-17 11:51:42 -07005880 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005881 return add_remove_audio_effect(stream, effect, true);
5882}
5883
5884static int in_remove_audio_effect(const struct audio_stream *stream,
5885 effect_handle_t effect)
5886{
Eric Laurent994a6932013-07-17 11:51:42 -07005887 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005888 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005889}
5890
Haynes Mathew George16081042017-05-31 17:16:49 -07005891static int in_stop(const struct audio_stream_in* stream)
5892{
5893 struct stream_in *in = (struct stream_in *)stream;
5894 struct audio_device *adev = in->dev;
5895
5896 int ret = -ENOSYS;
5897 ALOGV("%s", __func__);
5898 pthread_mutex_lock(&adev->lock);
5899 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5900 in->capture_started && in->pcm != NULL) {
5901 pcm_stop(in->pcm);
5902 ret = stop_input_stream(in);
5903 in->capture_started = false;
5904 }
5905 pthread_mutex_unlock(&adev->lock);
5906 return ret;
5907}
5908
5909static int in_start(const struct audio_stream_in* stream)
5910{
5911 struct stream_in *in = (struct stream_in *)stream;
5912 struct audio_device *adev = in->dev;
5913 int ret = -ENOSYS;
5914
5915 ALOGV("%s in %p", __func__, in);
5916 pthread_mutex_lock(&adev->lock);
5917 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5918 !in->capture_started && in->pcm != NULL) {
5919 if (!in->capture_started) {
5920 ret = start_input_stream(in);
5921 if (ret == 0) {
5922 in->capture_started = true;
5923 }
5924 }
5925 }
5926 pthread_mutex_unlock(&adev->lock);
5927 return ret;
5928}
5929
5930static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5931 int32_t min_size_frames,
5932 struct audio_mmap_buffer_info *info)
5933{
5934 struct stream_in *in = (struct stream_in *)stream;
5935 struct audio_device *adev = in->dev;
5936 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005937 unsigned int offset1 = 0;
5938 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005939 const char *step = "";
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005940 uint32_t mmap_size = 0;
5941 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005942
5943 pthread_mutex_lock(&adev->lock);
5944 ALOGV("%s in %p", __func__, in);
5945
Sharad Sangle90e613f2018-05-04 16:15:38 +05305946 if (CARD_STATUS_OFFLINE == in->card_status||
5947 CARD_STATUS_OFFLINE == adev->card_status) {
5948 ALOGW("in->card_status or adev->card_status offline, try again");
5949 ret = -EIO;
5950 goto exit;
5951 }
5952
Haynes Mathew George16081042017-05-31 17:16:49 -07005953 if (info == NULL || min_size_frames == 0) {
5954 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5955 ret = -EINVAL;
5956 goto exit;
5957 }
5958 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5959 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5960 ALOGV("%s in %p", __func__, in);
5961 ret = -ENOSYS;
5962 goto exit;
5963 }
5964 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5965 if (in->pcm_device_id < 0) {
5966 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5967 __func__, in->pcm_device_id, in->usecase);
5968 ret = -EINVAL;
5969 goto exit;
5970 }
5971
5972 adjust_mmap_period_count(&in->config, min_size_frames);
5973
5974 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5975 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5976 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5977 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305978 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
5979 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5980 in->card_status = CARD_STATUS_OFFLINE;
5981 adev->card_status = CARD_STATUS_OFFLINE;
5982 ret = -EIO;
5983 goto exit;
5984 }
5985
Haynes Mathew George16081042017-05-31 17:16:49 -07005986 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5987 step = "open";
5988 ret = -ENODEV;
5989 goto exit;
5990 }
5991
5992 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5993 if (ret < 0) {
5994 step = "begin";
5995 goto exit;
5996 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005997
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005998 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5999 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
6000 info->burst_size_frames = in->config.period_size;
6001 ret = platform_get_mmap_data_fd(adev->platform,
6002 in->pcm_device_id, 1 /*capture*/,
6003 &info->shared_memory_fd,
6004 &mmap_size);
6005 if (ret < 0) {
6006 // Fall back to non exclusive mode
6007 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6008 } else {
6009 if (mmap_size < buffer_size) {
6010 step = "mmap";
6011 goto exit;
6012 }
6013 // FIXME: indicate exclusive mode support by returning a negative buffer size
6014 info->buffer_size_frames *= -1;
6015 }
6016
6017 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006018
6019 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6020 if (ret < 0) {
6021 step = "commit";
6022 goto exit;
6023 }
6024
6025 in->standby = false;
6026 ret = 0;
6027
6028 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6029 __func__, info->shared_memory_address, info->buffer_size_frames);
6030
6031exit:
6032 if (ret != 0) {
6033 if (in->pcm == NULL) {
6034 ALOGE("%s: %s - %d", __func__, step, ret);
6035 } else {
6036 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6037 pcm_close(in->pcm);
6038 in->pcm = NULL;
6039 }
6040 }
6041 pthread_mutex_unlock(&adev->lock);
6042 return ret;
6043}
6044
6045static int in_get_mmap_position(const struct audio_stream_in *stream,
6046 struct audio_mmap_position *position)
6047{
6048 struct stream_in *in = (struct stream_in *)stream;
6049 ALOGVV("%s", __func__);
6050 if (position == NULL) {
6051 return -EINVAL;
6052 }
6053 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6054 return -ENOSYS;
6055 }
6056 if (in->pcm == NULL) {
6057 return -ENOSYS;
6058 }
6059 struct timespec ts = { 0, 0 };
6060 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6061 if (ret < 0) {
6062 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6063 return ret;
6064 }
Naresh Tannirua15d7e92018-11-02 09:49:44 +05306065 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07006066 return 0;
6067}
6068
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306069static int in_get_active_microphones(const struct audio_stream_in *stream,
6070 struct audio_microphone_characteristic_t *mic_array,
6071 size_t *mic_count) {
6072 struct stream_in *in = (struct stream_in *)stream;
6073 struct audio_device *adev = in->dev;
6074 ALOGVV("%s", __func__);
6075
6076 lock_input_stream(in);
6077 pthread_mutex_lock(&adev->lock);
6078 int ret = platform_get_active_microphones(adev->platform,
6079 audio_channel_count_from_in_mask(in->channel_mask),
6080 in->usecase, mic_array, mic_count);
6081 pthread_mutex_unlock(&adev->lock);
6082 pthread_mutex_unlock(&in->lock);
6083
6084 return ret;
6085}
6086
6087static int adev_get_microphones(const struct audio_hw_device *dev,
6088 struct audio_microphone_characteristic_t *mic_array,
6089 size_t *mic_count) {
6090 struct audio_device *adev = (struct audio_device *)dev;
6091 ALOGVV("%s", __func__);
6092
6093 pthread_mutex_lock(&adev->lock);
6094 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6095 pthread_mutex_unlock(&adev->lock);
6096
6097 return ret;
6098}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306099int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006100 audio_io_handle_t handle,
6101 audio_devices_t devices,
6102 audio_output_flags_t flags,
6103 struct audio_config *config,
6104 struct audio_stream_out **stream_out,
6105 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006106{
6107 struct audio_device *adev = (struct audio_device *)dev;
6108 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306109 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006110 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006111 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306112 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006113 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6114 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6115 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6116 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006117
kunleizdff872d2018-08-20 14:40:33 +08006118 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006119 is_usb_dev = false;
6120 devices = AUDIO_DEVICE_OUT_SPEAKER;
6121 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6122 __func__, devices);
6123 }
6124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006125 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306126
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006127 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6128
Mingming Yin3a941d42016-02-17 18:08:05 -08006129 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6130 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306131 devices, flags, &out->stream);
6132
6133
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006134 if (!out) {
6135 return -ENOMEM;
6136 }
6137
Haynes Mathew George204045b2015-02-25 20:32:03 -08006138 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006139 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306140 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006141 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006142 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6143
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006144 if (devices == AUDIO_DEVICE_NONE)
6145 devices = AUDIO_DEVICE_OUT_SPEAKER;
6146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006147 out->flags = flags;
6148 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006149 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006150 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006151 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306152 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306153 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6154 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6155 else
6156 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006157 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006158 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006159 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306160 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306161 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306162 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006163 out->hal_output_suspend_supported = 0;
6164 out->dynamic_pm_qos_config_supported = 0;
Surendar Karka5a18a7a2018-04-26 11:28:38 +05306165 out->set_dual_mono = false;
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05306166 out->prev_card_status_offline = false;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05306167 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006168
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306169 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306170 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006171 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6172
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006173 if (audio_is_linear_pcm(out->format) &&
6174 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
6175 pthread_mutex_lock(&adev->lock);
6176 if (is_hdmi) {
6177 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6178 ret = read_hdmi_sink_caps(out);
6179 } else if (is_usb_dev) {
6180 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6181 &config->format,
6182 &out->supported_formats[0],
6183 MAX_SUPPORTED_FORMATS,
6184 &config->channel_mask,
6185 &out->supported_channel_masks[0],
6186 MAX_SUPPORTED_CHANNEL_MASKS,
6187 &config->sample_rate,
6188 &out->supported_sample_rates[0],
6189 MAX_SUPPORTED_SAMPLE_RATES);
6190 ALOGV("plugged dev USB ret %d", ret);
6191 } else {
6192 ret = -1;
6193 }
6194 pthread_mutex_unlock(&adev->lock);
6195 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006196 if (ret == -ENOSYS) {
6197 /* ignore and go with default */
6198 ret = 0;
6199 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006200 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006201 goto error_open;
6202 }
6203 }
6204 }
6205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006206 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07006207#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006208 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6209 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6210 out->sample_rate == 32000 || out->sample_rate == 48000)) {
6211 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
6212 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
6213 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
6214
6215 out->config = default_pcm_config_voip_copp;
6216 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6217 out->config.rate = out->sample_rate;
6218
6219#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05306220 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006221 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08006222 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006223 ret = voice_extn_compress_voip_open_output_stream(out);
6224 if (ret != 0) {
6225 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6226 __func__, ret);
6227 goto error_open;
6228 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006229#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006230 } else if (audio_is_linear_pcm(out->format) &&
6231 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6232 out->channel_mask = config->channel_mask;
6233 out->sample_rate = config->sample_rate;
6234 out->format = config->format;
6235 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6236 // does this change?
6237 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6238 out->config.rate = config->sample_rate;
6239 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6240 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6241 audio_bytes_per_sample(config->format));
6242 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006243 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306244 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306245 pthread_mutex_lock(&adev->lock);
6246 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6247 pthread_mutex_unlock(&adev->lock);
6248
6249 // reject offload during card offline to allow
6250 // fallback to s/w paths
6251 if (offline) {
6252 ret = -ENODEV;
6253 goto error_open;
6254 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006255
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006256 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6257 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6258 ALOGE("%s: Unsupported Offload information", __func__);
6259 ret = -EINVAL;
6260 goto error_open;
6261 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006262
Atul Khare3fa6e542017-08-09 00:56:17 +05306263 if (config->offload_info.format == 0)
6264 config->offload_info.format = config->format;
6265 if (config->offload_info.sample_rate == 0)
6266 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006267
Mingming Yin90310102013-11-13 16:57:00 -08006268 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306269 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006270 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006271 ret = -EINVAL;
6272 goto error_open;
6273 }
6274
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006275 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6276 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6277 (audio_extn_passthru_is_passthrough_stream(out)) &&
6278 !((config->sample_rate == 48000) ||
6279 (config->sample_rate == 96000) ||
6280 (config->sample_rate == 192000))) {
6281 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6282 __func__, config->sample_rate, config->offload_info.format);
6283 ret = -EINVAL;
6284 goto error_open;
6285 }
6286
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006287 out->compr_config.codec = (struct snd_codec *)
6288 calloc(1, sizeof(struct snd_codec));
6289
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006290 if (!out->compr_config.codec) {
6291 ret = -ENOMEM;
6292 goto error_open;
6293 }
6294
Dhananjay Kumarac341582017-02-23 23:42:25 +05306295 out->stream.pause = out_pause;
6296 out->stream.resume = out_resume;
6297 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306298 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306299 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006300 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306301 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006302 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306303 } else {
6304 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6305 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006306 }
vivek mehta446c3962015-09-14 10:57:35 -07006307
6308 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006309 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6310 config->format == 0 && config->sample_rate == 0 &&
6311 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006312 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006313 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6314 } else {
6315 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6316 ret = -EEXIST;
6317 goto error_open;
6318 }
vivek mehta446c3962015-09-14 10:57:35 -07006319 }
6320
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006321 if (config->offload_info.channel_mask)
6322 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006323 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006324 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006325 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006326 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306327 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006328 ret = -EINVAL;
6329 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006330 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006331
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006332 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006333 out->sample_rate = config->offload_info.sample_rate;
6334
Mingming Yin3ee55c62014-08-04 14:23:35 -07006335 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006336
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306337 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306338 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306339 audio_extn_dolby_send_ddp_endp_params(adev);
6340 audio_extn_dolby_set_dmid(adev);
6341 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006342
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006343 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006344 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006345 out->compr_config.codec->bit_rate =
6346 config->offload_info.bit_rate;
6347 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306348 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006349 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306350 /* Update bit width only for non passthrough usecases.
6351 * For passthrough usecases, the output will always be opened @16 bit
6352 */
6353 if (!audio_extn_passthru_is_passthrough_stream(out))
6354 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306355
6356 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6357 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6358 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6359
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006360 /*TODO: Do we need to change it for passthrough */
6361 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006362
Manish Dewangana6fc5442015-08-24 20:30:31 +05306363 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6364 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306365 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306366 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306367 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6368 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306369
6370 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6371 AUDIO_FORMAT_PCM) {
6372
6373 /*Based on platform support, configure appropriate alsa format for corresponding
6374 *hal input format.
6375 */
6376 out->compr_config.codec->format = hal_format_to_alsa(
6377 config->offload_info.format);
6378
Ashish Jain83a6cc22016-06-28 14:34:17 +05306379 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306380 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306381 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306382
Dhananjay Kumarac341582017-02-23 23:42:25 +05306383 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306384 *hal input format and alsa format might differ based on platform support.
6385 */
6386 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306387 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306388
6389 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6390
6391 /* Check if alsa session is configured with the same format as HAL input format,
6392 * if not then derive correct fragment size needed to accomodate the
6393 * conversion of HAL input format to alsa format.
6394 */
6395 audio_extn_utils_update_direct_pcm_fragment_size(out);
6396
6397 /*if hal input and output fragment size is different this indicates HAL input format is
6398 *not same as the alsa format
6399 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306400 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306401 /*Allocate a buffer to convert input data to the alsa configured format.
6402 *size of convert buffer is equal to the size required to hold one fragment size
6403 *worth of pcm data, this is because flinger does not write more than fragment_size
6404 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306405 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6406 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306407 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6408 ret = -ENOMEM;
6409 goto error_open;
6410 }
6411 }
6412 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6413 out->compr_config.fragment_size =
6414 audio_extn_passthru_get_buffer_size(&config->offload_info);
6415 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6416 } else {
6417 out->compr_config.fragment_size =
6418 platform_get_compress_offload_buffer_size(&config->offload_info);
6419 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6420 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006421
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306422 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6423 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6424 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006425 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306426 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006427
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306428 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6429 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6430 }
6431
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006432 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6433 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006434
Manish Dewangan69426c82017-01-30 17:35:36 +05306435 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6436 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6437 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6438 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6439 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6440 } else {
6441 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6442 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006443
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306444 memset(&out->channel_map_param, 0,
6445 sizeof(struct audio_out_channel_map_param));
6446
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006447 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306448 out->send_next_track_params = false;
6449 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006450 out->offload_state = OFFLOAD_STATE_IDLE;
6451 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006452 out->writeAt.tv_sec = 0;
6453 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006454
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006455 audio_extn_dts_create_state_notifier_node(out->usecase);
6456
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006457 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6458 __func__, config->offload_info.version,
6459 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306460
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306461 /* Check if DSD audio format is supported in codec
6462 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306463 */
6464
6465 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306466 (!platform_check_codec_dsd_support(adev->platform) ||
6467 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306468 ret = -EINVAL;
6469 goto error_open;
6470 }
6471
Ashish Jain5106d362016-05-11 19:23:33 +05306472 /* Disable gapless if any of the following is true
6473 * passthrough playback
6474 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306475 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306476 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306477 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306478 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006479 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306480 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306481 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306482 check_and_set_gapless_mode(adev, false);
6483 } else
6484 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006485
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306486 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006487 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6488 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306489 if (config->format == AUDIO_FORMAT_DSD) {
6490 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6491 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6492 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006493
6494 create_offload_callback_thread(out);
6495
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006496 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006497 switch (config->sample_rate) {
6498 case 0:
6499 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6500 break;
6501 case 8000:
6502 case 16000:
6503 case 48000:
6504 out->sample_rate = config->sample_rate;
6505 break;
6506 default:
6507 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
6508 config->sample_rate);
6509 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6510 ret = -EINVAL;
6511 goto error_open;
6512 }
6513 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6514 switch (config->channel_mask) {
6515 case AUDIO_CHANNEL_NONE:
6516 case AUDIO_CHANNEL_OUT_STEREO:
6517 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6518 break;
6519 default:
6520 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
6521 config->channel_mask);
6522 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6523 ret = -EINVAL;
6524 goto error_open;
6525 }
6526 switch (config->format) {
6527 case AUDIO_FORMAT_DEFAULT:
6528 case AUDIO_FORMAT_PCM_16_BIT:
6529 out->format = AUDIO_FORMAT_PCM_16_BIT;
6530 break;
6531 default:
6532 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
6533 config->format);
6534 config->format = AUDIO_FORMAT_PCM_16_BIT;
6535 ret = -EINVAL;
6536 goto error_open;
6537 }
6538
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306539 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006540 if (ret != 0) {
6541 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006542 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006543 goto error_open;
6544 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006545 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006546 if (config->sample_rate == 0)
6547 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6548 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6549 config->sample_rate != 8000) {
6550 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6551 ret = -EINVAL;
6552 goto error_open;
6553 }
6554 out->sample_rate = config->sample_rate;
6555 out->config.rate = config->sample_rate;
6556 if (config->format == AUDIO_FORMAT_DEFAULT)
6557 config->format = AUDIO_FORMAT_PCM_16_BIT;
6558 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6559 config->format = AUDIO_FORMAT_PCM_16_BIT;
6560 ret = -EINVAL;
6561 goto error_open;
6562 }
6563 out->format = config->format;
6564 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
6565 out->config = pcm_config_afe_proxy_playback;
6566 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006567 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05306568 unsigned int channels = 0;
6569 /*Update config params to default if not set by the caller*/
6570 if (config->sample_rate == 0)
6571 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6572 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6573 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6574 if (config->format == AUDIO_FORMAT_DEFAULT)
6575 config->format = AUDIO_FORMAT_PCM_16_BIT;
6576
6577 channels = audio_channel_count_from_out_mask(out->channel_mask);
6578
Varun Balaraje49253e2017-07-06 19:48:56 +05306579 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6580 out->usecase = get_interactive_usecase(adev);
6581 out->config = pcm_config_low_latency;
6582 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306583 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006584 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6585 out->flags);
6586 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006587 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6588 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6589 out->config = pcm_config_mmap_playback;
6590 out->stream.start = out_start;
6591 out->stream.stop = out_stop;
6592 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6593 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306594 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6595 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006596 out->hal_output_suspend_supported =
6597 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6598 out->dynamic_pm_qos_config_supported =
6599 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6600 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006601 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6602 } else {
6603 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6604 //the mixer path will be a string similar to "low-latency-playback resume"
6605 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6606 strlcat(out->pm_qos_mixer_path,
6607 " resume", MAX_MIXER_PATH_LEN);
6608 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6609 out->pm_qos_mixer_path);
6610 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306611 out->config = pcm_config_low_latency;
6612 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6613 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6614 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306615 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6616 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6617 if (out->config.period_size <= 0) {
6618 ALOGE("Invalid configuration period size is not valid");
6619 ret = -EINVAL;
6620 goto error_open;
6621 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306622 } else {
6623 /* primary path is the default path selected if no other outputs are available/suitable */
6624 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6625 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6626 }
6627 out->hal_ip_format = format = out->format;
6628 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6629 out->hal_op_format = pcm_format_to_hal(out->config.format);
6630 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6631 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006632 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306633 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306634 if (out->hal_ip_format != out->hal_op_format) {
6635 uint32_t buffer_size = out->config.period_size *
6636 format_to_bitwidth_table[out->hal_op_format] *
6637 out->config.channels;
6638 out->convert_buffer = calloc(1, buffer_size);
6639 if (out->convert_buffer == NULL){
6640 ALOGE("Allocation failed for convert buffer for size %d",
6641 out->compr_config.fragment_size);
6642 ret = -ENOMEM;
6643 goto error_open;
6644 }
6645 ALOGD("Convert buffer allocated of size %d", buffer_size);
6646 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006647 }
6648
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006649 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6650 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306651
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006652 /* TODO remove this hardcoding and check why width is zero*/
6653 if (out->bit_width == 0)
6654 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306655 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006656 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006657 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306658 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306659 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006660 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6661 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6662 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006663 if(adev->primary_output == NULL)
6664 adev->primary_output = out;
6665 else {
6666 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006667 ret = -EEXIST;
6668 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006669 }
6670 }
6671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006672 /* Check if this usecase is already existing */
6673 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006674 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6675 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006676 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006677 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006678 ret = -EEXIST;
6679 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006680 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006681
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006682 pthread_mutex_unlock(&adev->lock);
6683
6684 out->stream.common.get_sample_rate = out_get_sample_rate;
6685 out->stream.common.set_sample_rate = out_set_sample_rate;
6686 out->stream.common.get_buffer_size = out_get_buffer_size;
6687 out->stream.common.get_channels = out_get_channels;
6688 out->stream.common.get_format = out_get_format;
6689 out->stream.common.set_format = out_set_format;
6690 out->stream.common.standby = out_standby;
6691 out->stream.common.dump = out_dump;
6692 out->stream.common.set_parameters = out_set_parameters;
6693 out->stream.common.get_parameters = out_get_parameters;
6694 out->stream.common.add_audio_effect = out_add_audio_effect;
6695 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6696 out->stream.get_latency = out_get_latency;
6697 out->stream.set_volume = out_set_volume;
6698 out->stream.write = out_write;
6699 out->stream.get_render_position = out_get_render_position;
6700 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006701 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006702
Haynes Mathew George16081042017-05-31 17:16:49 -07006703 if (out->realtime)
6704 out->af_period_multiplier = af_period_multiplier;
6705 else
6706 out->af_period_multiplier = 1;
6707
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006708 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006709 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006710 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006711
6712 config->format = out->stream.common.get_format(&out->stream.common);
6713 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6714 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05306715 register_format(out->format, out->supported_formats);
6716 register_channel_mask(out->channel_mask, out->supported_channel_masks);
6717 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006718
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306719 /*
6720 By locking output stream before registering, we allow the callback
6721 to update stream's state only after stream's initial state is set to
6722 adev state.
6723 */
6724 lock_output_stream(out);
6725 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6726 pthread_mutex_lock(&adev->lock);
6727 out->card_status = adev->card_status;
6728 pthread_mutex_unlock(&adev->lock);
6729 pthread_mutex_unlock(&out->lock);
6730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006731 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306732 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006733 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006734
6735 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6736 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6737 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006738 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306739 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006740 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006741 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306742 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006743 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6744 out->usecase, PCM_PLAYBACK);
6745 hdlr_stream_cfg.flags = out->flags;
6746 hdlr_stream_cfg.type = PCM_PLAYBACK;
6747 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6748 &hdlr_stream_cfg);
6749 if (ret) {
6750 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6751 out->adsp_hdlr_stream_handle = NULL;
6752 }
6753 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306754 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006755 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006756 if (ret < 0) {
6757 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6758 out->ip_hdlr_handle = NULL;
6759 }
6760 }
Eric Laurent994a6932013-07-17 11:51:42 -07006761 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006762 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006763
6764error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306765 if (out->convert_buffer)
6766 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006767 free(out);
6768 *stream_out = NULL;
6769 ALOGD("%s: exit: ret %d", __func__, ret);
6770 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006771}
6772
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306773void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006774 struct audio_stream_out *stream)
6775{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006776 struct stream_out *out = (struct stream_out *)stream;
6777 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006778 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006779
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006780 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306781
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306782 // must deregister from sndmonitor first to prevent races
6783 // between the callback and close_stream
6784 audio_extn_snd_mon_unregister_listener(out);
6785
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006786 /* close adsp hdrl session before standby */
6787 if (out->adsp_hdlr_stream_handle) {
6788 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6789 if (ret)
6790 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6791 out->adsp_hdlr_stream_handle = NULL;
6792 }
6793
Manish Dewangan21a850a2017-08-14 12:03:55 +05306794 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006795 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6796 out->ip_hdlr_handle = NULL;
6797 }
6798
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006799 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306800 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006801 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306802 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306803 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006804 if(ret != 0)
6805 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6806 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006807 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006808 out_standby(&stream->common);
6809
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006810 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006811 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006812 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006813 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006814 if (out->compr_config.codec != NULL)
6815 free(out->compr_config.codec);
6816 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006817
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306818 out->a2dp_compress_mute = false;
6819
Varun Balaraje49253e2017-07-06 19:48:56 +05306820 if (is_interactive_usecase(out->usecase))
6821 free_interactive_usecase(adev, out->usecase);
6822
Ashish Jain83a6cc22016-06-28 14:34:17 +05306823 if (out->convert_buffer != NULL) {
6824 free(out->convert_buffer);
6825 out->convert_buffer = NULL;
6826 }
6827
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006828 if (adev->voice_tx_output == out)
6829 adev->voice_tx_output = NULL;
6830
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306831 if (adev->primary_output == out)
6832 adev->primary_output = NULL;
6833
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006834 pthread_cond_destroy(&out->cond);
6835 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006836 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006837 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006838}
6839
6840static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6841{
6842 struct audio_device *adev = (struct audio_device *)dev;
6843 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006844 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006845 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006846 int ret;
6847 int status = 0;
Zhou Songa32012a2019-05-21 18:08:51 +08006848 struct listnode *node;
6849 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006850
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006851 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006852 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006853
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306854 if (!parms)
6855 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306856
Zhou Songa32012a2019-05-21 18:08:51 +08006857 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306858 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6859 if (ret >= 0) {
6860 /* When set to false, HAL should disable EC and NS */
Zhou Songa32012a2019-05-21 18:08:51 +08006861 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306862 adev->bt_sco_on = true;
Zhou Songa32012a2019-05-21 18:08:51 +08006863 } else {
6864 ALOGD("route device to handset/mic when sco is off");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306865 adev->bt_sco_on = false;
Zhou Songa32012a2019-05-21 18:08:51 +08006866 list_for_each(node, &adev->usecase_list) {
6867 usecase = node_to_item(node, struct audio_usecase, list);
6868 if ((usecase->type == PCM_PLAYBACK) && usecase->stream.out &&
6869 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_SCO))
6870 usecase->stream.out->devices = AUDIO_DEVICE_OUT_EARPIECE;
6871 else if ((usecase->type == PCM_CAPTURE) && usecase->stream.in &&
6872 (usecase->stream.in->device & AUDIO_DEVICE_IN_ALL_SCO))
6873 usecase->stream.in->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
6874 else
6875 continue;
6876 select_devices(adev, usecase->id);
6877 }
6878 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306879 }
6880
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006881 status = voice_set_parameters(adev, parms);
6882 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006883 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006884
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006885 status = platform_set_parameters(adev->platform, parms);
6886 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006887 goto done;
6888
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006889 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6890 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006891 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006892 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6893 adev->bluetooth_nrec = true;
6894 else
6895 adev->bluetooth_nrec = false;
6896 }
6897
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006898 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6899 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006900 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6901 adev->screen_off = false;
6902 else
6903 adev->screen_off = true;
6904 }
6905
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006906 ret = str_parms_get_int(parms, "rotation", &val);
6907 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006908 bool reverse_speakers = false;
6909 switch(val) {
6910 // FIXME: note that the code below assumes that the speakers are in the correct placement
6911 // relative to the user when the device is rotated 90deg from its default rotation. This
6912 // assumption is device-specific, not platform-specific like this code.
6913 case 270:
6914 reverse_speakers = true;
6915 break;
6916 case 0:
6917 case 90:
6918 case 180:
6919 break;
6920 default:
6921 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006922 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006923 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006924 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006925 // check and set swap
6926 // - check if orientation changed and speaker active
6927 // - set rotation and cache the rotation value
6928 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006929 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006930 }
6931
Mingming Yin514a8bc2014-07-29 15:22:21 -07006932 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6933 if (ret >= 0) {
6934 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6935 adev->bt_wb_speech_enabled = true;
6936 else
6937 adev->bt_wb_speech_enabled = false;
6938 }
6939
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006940 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6941 if (ret >= 0) {
6942 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306943 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08006944 if (audio_is_output_device(val) &&
6945 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006946 ALOGV("cache new ext disp type and edid");
6947 ret = platform_get_ext_disp_type(adev->platform);
6948 if (ret < 0) {
6949 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05306950 } else {
6951 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006952 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306953 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07006954 /*
6955 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6956 * Per AudioPolicyManager, USB device is higher priority than WFD.
6957 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6958 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6959 * starting voice call on USB
6960 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006961 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306962 if (ret >= 0)
6963 audio_extn_usb_add_device(device, atoi(value));
6964
Zhou Song6f862822017-11-06 17:27:57 +08006965 if (!audio_extn_usb_is_tunnel_supported()) {
6966 ALOGV("detected USB connect .. disable proxy");
6967 adev->allow_afe_proxy_usage = false;
6968 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006969 }
6970 }
6971
6972 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6973 if (ret >= 0) {
6974 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306975 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07006976 /*
6977 * The HDMI / Displayport disconnect handling has been moved to
6978 * audio extension to ensure that its parameters are not
6979 * invalidated prior to updating sysfs of the disconnect event
6980 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6981 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306982 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006983 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306984 if (ret >= 0)
6985 audio_extn_usb_remove_device(device, atoi(value));
6986
Zhou Song6f862822017-11-06 17:27:57 +08006987 if (!audio_extn_usb_is_tunnel_supported()) {
6988 ALOGV("detected USB disconnect .. enable proxy");
6989 adev->allow_afe_proxy_usage = true;
6990 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006991 }
6992 }
6993
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306994 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6995 if (ret >= 0) {
6996 struct audio_usecase *usecase;
6997 struct listnode *node;
6998 list_for_each(node, &adev->usecase_list) {
6999 usecase = node_to_item(node, struct audio_usecase, list);
7000 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07007001 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307002 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08007003
7004 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307005 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08007006 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307007 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307008 //force device switch to re configure encoder
7009 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307010 audio_extn_a2dp_set_handoff_mode(false);
7011 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307012 break;
7013 }
7014 }
7015 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007016
7017 //handle vr audio setparam
7018 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7019 value, sizeof(value));
7020 if (ret >= 0) {
7021 ALOGI("Setting vr mode to be %s", value);
7022 if (!strncmp(value, "true", 4)) {
7023 adev->vr_audio_mode_enabled = true;
7024 ALOGI("Setting vr mode to true");
7025 } else if (!strncmp(value, "false", 5)) {
7026 adev->vr_audio_mode_enabled = false;
7027 ALOGI("Setting vr mode to false");
7028 } else {
7029 ALOGI("wrong vr mode set");
7030 }
7031 }
7032
Balázs Triszka6e101332018-02-26 22:11:10 +01007033 ret = str_parms_get_int(parms, "ultrasound_enable", &val);
7034 if (ret >= 0) {
7035 if (val == 1) {
7036 us_start();
7037 } else {
7038 us_stop();
7039 }
7040 }
7041
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307042 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007043done:
7044 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007045 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307046error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007047 ALOGV("%s: exit with code(%d)", __func__, status);
7048 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007049}
7050
7051static char* adev_get_parameters(const struct audio_hw_device *dev,
7052 const char *keys)
7053{
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05307054 ALOGD("%s:%s", __func__, keys);
7055
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007056 struct audio_device *adev = (struct audio_device *)dev;
7057 struct str_parms *reply = str_parms_create();
7058 struct str_parms *query = str_parms_create_str(keys);
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05307059
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007060 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05307061 char value[256] = {0};
7062 int ret = 0;
7063
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007064 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007065 if (reply) {
7066 str_parms_destroy(reply);
7067 }
7068 if (query) {
7069 str_parms_destroy(query);
7070 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007071 ALOGE("adev_get_parameters: failed to create query or reply");
7072 return NULL;
7073 }
7074
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007075 //handle vr audio getparam
7076
7077 ret = str_parms_get_str(query,
7078 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7079 value, sizeof(value));
7080
7081 if (ret >= 0) {
7082 bool vr_audio_enabled = false;
7083 pthread_mutex_lock(&adev->lock);
7084 vr_audio_enabled = adev->vr_audio_mode_enabled;
7085 pthread_mutex_unlock(&adev->lock);
7086
7087 ALOGI("getting vr mode to %d", vr_audio_enabled);
7088
7089 if (vr_audio_enabled) {
7090 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7091 "true");
7092 goto exit;
7093 } else {
7094 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7095 "false");
7096 goto exit;
7097 }
7098 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007099
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007100 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007101 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08007102 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007103 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05307104 pthread_mutex_unlock(&adev->lock);
7105
Naresh Tannirud7205b62014-06-20 02:54:48 +05307106exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007107 str = str_parms_to_str(reply);
7108 str_parms_destroy(query);
7109 str_parms_destroy(reply);
7110
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05307111 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007112 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007113}
7114
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007115static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007116{
7117 return 0;
7118}
7119
7120static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
7121{
Haynes Mathew George5191a852013-09-11 14:19:36 -07007122 int ret;
7123 struct audio_device *adev = (struct audio_device *)dev;
7124 pthread_mutex_lock(&adev->lock);
7125 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07007126 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07007127 pthread_mutex_unlock(&adev->lock);
7128 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007129}
7130
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007131static int adev_set_master_volume(struct audio_hw_device *dev __unused,
7132 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007133{
7134 return -ENOSYS;
7135}
7136
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007137static int adev_get_master_volume(struct audio_hw_device *dev __unused,
7138 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007139{
7140 return -ENOSYS;
7141}
7142
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007143static int adev_set_master_mute(struct audio_hw_device *dev __unused,
7144 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007145{
7146 return -ENOSYS;
7147}
7148
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007149static int adev_get_master_mute(struct audio_hw_device *dev __unused,
7150 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007151{
7152 return -ENOSYS;
7153}
7154
7155static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
7156{
7157 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07007158 struct listnode *node;
7159 struct audio_usecase *usecase = NULL;
7160 int ret = 0;
kunleiz60c17e72017-05-04 12:15:35 +08007161
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007162 pthread_mutex_lock(&adev->lock);
7163 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007164 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007165 adev->mode = mode;
Kunlei Zhang0eab0432019-05-21 14:25:57 +08007166 if (voice_is_in_call(adev) &&
7167 (mode == AUDIO_MODE_NORMAL ||
7168 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07007169 list_for_each(node, &adev->usecase_list) {
7170 usecase = node_to_item(node, struct audio_usecase, list);
7171 if (usecase->type == VOICE_CALL)
7172 break;
7173 }
7174 if (usecase &&
7175 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
7176 ret = audio_extn_usb_check_and_set_svc_int(usecase,
7177 true);
7178 if (ret != 0) {
7179 /* default service interval was successfully updated,
7180 reopen USB backend with new service interval */
7181 check_usecases_codec_backend(adev,
7182 usecase,
7183 usecase->out_snd_device);
7184 }
7185 }
7186
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007187 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07007188 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007189 adev->current_call_output = NULL;
kunleiz60c17e72017-05-04 12:15:35 +08007190 // restore device for other active usecases after stop call
7191 list_for_each(node, &adev->usecase_list) {
7192 usecase = node_to_item(node, struct audio_usecase, list);
7193 select_devices(adev, usecase->id);
7194 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007195 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007196 }
7197 pthread_mutex_unlock(&adev->lock);
7198 return 0;
7199}
7200
7201static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
7202{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007203 int ret;
7204
7205 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08007206 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007207 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Derek Chencdd17c72014-11-24 12:39:14 -08007208 if (adev->ext_hw_plugin)
7209 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007210 pthread_mutex_unlock(&adev->lock);
7211
7212 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007213}
7214
7215static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
7216{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007217 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007218 return 0;
7219}
7220
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007221static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007222 const struct audio_config *config)
7223{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007224 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007225
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007226 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
7227 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007228}
7229
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007230static bool adev_input_allow_hifi_record(struct audio_device *adev,
7231 audio_devices_t devices,
7232 audio_input_flags_t flags,
7233 audio_source_t source) {
7234 const bool allowed = true;
7235
7236 if (!audio_is_usb_in_device(devices))
7237 return !allowed;
7238
7239 switch (flags) {
7240 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007241 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07007242 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7243 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007244 default:
7245 return !allowed;
7246 }
7247
7248 switch (source) {
7249 case AUDIO_SOURCE_DEFAULT:
7250 case AUDIO_SOURCE_MIC:
7251 case AUDIO_SOURCE_UNPROCESSED:
7252 break;
7253 default:
7254 return !allowed;
7255 }
7256
7257 switch (adev->mode) {
7258 case 0:
7259 break;
7260 default:
7261 return !allowed;
7262 }
7263
7264 return allowed;
7265}
7266
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007267static int adev_update_voice_comm_input_stream(struct stream_in *in,
7268 struct audio_config *config)
7269{
7270 bool valid_rate = (config->sample_rate == 8000 ||
7271 config->sample_rate == 16000 ||
7272 config->sample_rate == 32000 ||
7273 config->sample_rate == 48000);
7274 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
7275
7276#ifndef COMPRESS_VOIP_ENABLED
kunleizd96526c2018-04-09 11:12:32 +08007277 if (valid_rate && valid_ch &&
7278 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007279 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7280 in->config = default_pcm_config_voip_copp;
7281 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
7282 DEFAULT_VOIP_BUF_DURATION_MS,
7283 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
7284 } else {
kunleizbdd9ad02018-04-24 10:53:17 +08007285 ALOGW("%s No valid input in voip, use defaults"
7286 "sample rate %u, channel mask 0x%X",
7287 __func__, config->sample_rate, in->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007288 }
7289 in->config.rate = config->sample_rate;
7290 in->sample_rate = config->sample_rate;
7291#else
7292 //XXX needed for voice_extn_compress_voip_open_input_stream
7293 in->config.rate = config->sample_rate;
7294 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7295 voice_extn_compress_voip_is_active(in->dev)) &&
7296 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7297 valid_rate && valid_ch) {
7298 voice_extn_compress_voip_open_input_stream(in);
7299 // update rate entries to match config from AF
7300 in->config.rate = config->sample_rate;
7301 in->sample_rate = config->sample_rate;
7302 } else {
7303 ALOGW("%s compress voip not active, use defaults", __func__);
7304 }
7305#endif
7306 return 0;
7307}
7308
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007309static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007310 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007311 audio_devices_t devices,
7312 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007313 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307314 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007315 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007316 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007317{
7318 struct audio_device *adev = (struct audio_device *)dev;
7319 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007320 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007321 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007322 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05307323 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007324 bool is_usb_dev = audio_is_usb_in_device(devices);
7325 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
7326 devices,
7327 flags,
7328 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307329
kunleizdff872d2018-08-20 14:40:33 +08007330 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007331 is_usb_dev = false;
7332 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
7333 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
7334 __func__, devices);
7335 }
7336
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007337 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007338
7339 if (!(is_usb_dev && may_use_hifi_record)) {
7340 if (config->sample_rate == 0)
7341 config->sample_rate = 48000;
7342 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7343 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7344 if (config->format == AUDIO_FORMAT_DEFAULT)
7345 config->format = AUDIO_FORMAT_PCM_16_BIT;
7346
7347 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
7348
7349 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
7350 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05307351 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007352
7353 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007354
7355 if (!in) {
7356 ALOGE("failed to allocate input stream");
7357 return -ENOMEM;
7358 }
7359
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307360 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307361 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7362 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007363 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007364 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007365
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007366 in->stream.common.get_sample_rate = in_get_sample_rate;
7367 in->stream.common.set_sample_rate = in_set_sample_rate;
7368 in->stream.common.get_buffer_size = in_get_buffer_size;
7369 in->stream.common.get_channels = in_get_channels;
7370 in->stream.common.get_format = in_get_format;
7371 in->stream.common.set_format = in_set_format;
7372 in->stream.common.standby = in_standby;
7373 in->stream.common.dump = in_dump;
7374 in->stream.common.set_parameters = in_set_parameters;
7375 in->stream.common.get_parameters = in_get_parameters;
7376 in->stream.common.add_audio_effect = in_add_audio_effect;
7377 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7378 in->stream.set_gain = in_set_gain;
7379 in->stream.read = in_read;
7380 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307381 in->stream.get_active_microphones = in_get_active_microphones;
Ramjee Singhacef98f2019-06-28 11:01:25 +05307382#if ANDROID_PLATFORM_SDK_VERSION >= 29
7383 in->stream.set_microphone_direction = in_set_microphone_direction;
7384 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
7385#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007386
7387 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007388 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007389 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007390 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007391 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007392 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007393 in->bit_width = 16;
7394 in->af_period_multiplier = 1;
7395
7396 /* Update config params with the requested sample rate and channels */
7397 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
7398 (adev->mode != AUDIO_MODE_IN_CALL)) {
7399 ret = -EINVAL;
7400 goto err_open;
7401 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007402
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007403 if (is_usb_dev && may_use_hifi_record) {
7404 /* HiFi record selects an appropriate format, channel, rate combo
7405 depending on sink capabilities*/
7406 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7407 &config->format,
7408 &in->supported_formats[0],
7409 MAX_SUPPORTED_FORMATS,
7410 &config->channel_mask,
7411 &in->supported_channel_masks[0],
7412 MAX_SUPPORTED_CHANNEL_MASKS,
7413 &config->sample_rate,
7414 &in->supported_sample_rates[0],
7415 MAX_SUPPORTED_SAMPLE_RATES);
7416 if (ret != 0) {
7417 ret = -EINVAL;
7418 goto err_open;
7419 }
7420 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007421 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307422 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05307423 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
7424 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
7425 in->config.format = PCM_FORMAT_S32_LE;
7426 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307427 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
7428 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
7429 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
7430 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7431 bool ret_error = false;
7432 in->bit_width = 24;
7433 /* 24 bit is restricted to UNPROCESSED source only,also format supported
7434 from HAL is 24_packed and 8_24
7435 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
7436 24_packed return error indicating supported format is 24_packed
7437 *> In case of any other source requesting 24 bit or float return error
7438 indicating format supported is 16 bit only.
7439
7440 on error flinger will retry with supported format passed
7441 */
7442 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
7443 (source != AUDIO_SOURCE_CAMCORDER)) {
7444 config->format = AUDIO_FORMAT_PCM_16_BIT;
7445 if (config->sample_rate > 48000)
7446 config->sample_rate = 48000;
7447 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07007448 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
7449 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307450 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
7451 ret_error = true;
7452 }
7453
7454 if (ret_error) {
7455 ret = -EINVAL;
7456 goto err_open;
7457 }
7458 }
7459
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007460 in->channel_mask = config->channel_mask;
7461 in->format = config->format;
7462
7463 in->usecase = USECASE_AUDIO_RECORD;
7464 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
7465 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
7466 is_low_latency = true;
7467#if LOW_LATENCY_CAPTURE_USE_CASE
7468 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
7469#endif
7470 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
7471 }
7472
7473 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
7474 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
7475 in->realtime = 0;
7476 in->usecase = USECASE_AUDIO_RECORD_MMAP;
7477 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07007478 in->config.format = pcm_format_from_audio_format(config->format);
Weiyin Jiangde7925e2018-11-27 18:45:53 +08007479 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007480 in->stream.start = in_start;
7481 in->stream.stop = in_stop;
7482 in->stream.create_mmap_buffer = in_create_mmap_buffer;
7483 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007484 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007485 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
7486 } else if (in->realtime) {
7487 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07007488 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007489 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007490 in->sample_rate = in->config.rate;
7491 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07007492 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007493 in->usecase = USECASE_AUDIO_RECORD_HIFI;
7494 in->config = pcm_config_audio_capture;
7495 frame_size = audio_stream_in_frame_size(&in->stream);
7496 buffer_size = get_input_buffer_size(config->sample_rate,
7497 config->format,
7498 channel_count,
7499 false /*is_low_latency*/);
7500 in->config.period_size = buffer_size / frame_size;
7501 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007502 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07007503 switch (config->format) {
7504 case AUDIO_FORMAT_PCM_32_BIT:
7505 in->bit_width = 32;
7506 break;
7507 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
7508 case AUDIO_FORMAT_PCM_8_24_BIT:
7509 in->bit_width = 24;
7510 break;
7511 default:
7512 in->bit_width = 16;
7513 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007514 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007515 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007516 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05307517 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007518 if (config->sample_rate == 0)
7519 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7520 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
7521 config->sample_rate != 8000) {
7522 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7523 ret = -EINVAL;
7524 goto err_open;
7525 }
7526 if (config->format == AUDIO_FORMAT_DEFAULT)
7527 config->format = AUDIO_FORMAT_PCM_16_BIT;
7528 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
7529 config->format = AUDIO_FORMAT_PCM_16_BIT;
7530 ret = -EINVAL;
7531 goto err_open;
7532 }
7533
7534 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
7535 in->config = pcm_config_afe_proxy_record;
7536 in->config.channels = channel_count;
7537 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307538 in->sample_rate = config->sample_rate;
Haynes Mathew George46740472017-10-27 18:40:12 -07007539 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05307540 int ret_val;
7541 pthread_mutex_lock(&adev->lock);
7542 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
7543 in, config, &channel_mask_updated);
7544 pthread_mutex_unlock(&adev->lock);
7545
7546 if (!ret_val) {
7547 if (channel_mask_updated == true) {
7548 ALOGD("%s: return error to retry with updated channel mask (%#x)",
7549 __func__, config->channel_mask);
7550 ret = -EINVAL;
7551 goto err_open;
7552 }
7553 ALOGD("%s: created multi-channel session succesfully",__func__);
7554 } else if (audio_extn_compr_cap_enabled() &&
7555 audio_extn_compr_cap_format_supported(config->format) &&
7556 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
7557 audio_extn_compr_cap_init(in);
7558 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05307559 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05307560 ret = audio_extn_cin_configure_input_stream(in);
7561 if (ret)
7562 goto err_open;
7563 } else {
7564 in->config = pcm_config_audio_capture;
7565 in->config.rate = config->sample_rate;
7566 in->config.format = pcm_format_from_audio_format(config->format);
7567 in->config.channels = channel_count;
7568 in->sample_rate = config->sample_rate;
7569 in->format = config->format;
7570 frame_size = audio_stream_in_frame_size(&in->stream);
7571 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07007572 config->format,
7573 channel_count,
7574 is_low_latency);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307575 in->config.period_size = buffer_size / frame_size;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007576
Revathi Uddarajud2634032017-12-07 14:42:34 +05307577 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
7578 /* optionally use VOIP usecase depending on config(s) */
7579 ret = adev_update_voice_comm_input_stream(in, config);
7580 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007581
Revathi Uddarajud2634032017-12-07 14:42:34 +05307582 if (ret) {
7583 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
7584 goto err_open;
7585 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007586 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007587 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307588 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7589 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007590 devices, flags, in->format,
7591 in->sample_rate, in->bit_width,
7592 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307593 register_format(in->format, in->supported_formats);
7594 register_channel_mask(in->channel_mask, in->supported_channel_masks);
7595 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307596
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007597 /* This stream could be for sound trigger lab,
7598 get sound trigger pcm if present */
7599 audio_extn_sound_trigger_check_and_get_session(in);
7600
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307601 lock_input_stream(in);
7602 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
7603 pthread_mutex_lock(&adev->lock);
7604 in->card_status = adev->card_status;
7605 pthread_mutex_unlock(&adev->lock);
7606 pthread_mutex_unlock(&in->lock);
7607
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007608 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07007609 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007610 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007611
7612err_open:
7613 free(in);
7614 *stream_in = NULL;
7615 return ret;
7616}
7617
7618static void adev_close_input_stream(struct audio_hw_device *dev,
7619 struct audio_stream_in *stream)
7620{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007621 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007622 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007623 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307624
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307625 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007626
kunleizef40adb2018-12-28 17:50:23 +08007627 /* must deregister from sndmonitor first to prevent races
7628 * between the callback and close_stream
7629 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307630 audio_extn_snd_mon_unregister_listener(stream);
7631
kunleizef40adb2018-12-28 17:50:23 +08007632 /* Disable echo reference if there are no active input, hfp call
7633 * and sound trigger while closing input stream
7634 */
7635 if (!adev->active_input &&
7636 !audio_extn_hfp_is_active(adev) &&
7637 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8405edd2018-11-29 15:04:56 +08007638 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleizef40adb2018-12-28 17:50:23 +08007639 else
7640 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307641
Pallavid7c7a272018-01-16 11:22:55 +05307642 if (in == NULL) {
7643 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
7644 return;
7645 }
7646
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007647 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307648 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007649 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307650 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007651 if (ret != 0)
7652 ALOGE("%s: Compress voip input cannot be closed, error:%d",
7653 __func__, ret);
7654 } else
7655 in_standby(&stream->common);
7656
Revathi Uddarajud2634032017-12-07 14:42:34 +05307657 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07007658 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007659 audio_extn_ssr_deinit();
7660 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007661
Garmond Leunge2433c32017-09-28 21:51:22 -07007662 if (audio_extn_ffv_get_stream() == in) {
7663 audio_extn_ffv_stream_deinit();
7664 }
7665
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307666 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07007667 audio_extn_compr_cap_format_supported(in->config.format))
7668 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05307669
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307670 if (audio_extn_cin_attached_usecase(in->usecase))
7671 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007672
Mingming Yinfd7607b2016-01-22 12:48:44 -08007673 if (in->is_st_session) {
7674 ALOGV("%s: sound trigger pcm stop lab", __func__);
7675 audio_extn_sound_trigger_stop_lab(in);
7676 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007677 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307678 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007679 return;
7680}
7681
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307682int adev_create_audio_patch(struct audio_hw_device *dev,
7683 unsigned int num_sources,
7684 const struct audio_port_config *sources,
7685 unsigned int num_sinks,
7686 const struct audio_port_config *sinks,
7687 audio_patch_handle_t *handle)
7688{
7689
7690
7691 return audio_extn_hw_loopback_create_audio_patch(dev,
7692 num_sources,
7693 sources,
7694 num_sinks,
7695 sinks,
7696 handle);
7697
7698}
7699
7700int adev_release_audio_patch(struct audio_hw_device *dev,
7701 audio_patch_handle_t handle)
7702{
7703 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
7704}
7705
7706int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
7707{
7708 return audio_extn_hw_loopback_get_audio_port(dev, config);
7709}
7710
7711int adev_set_audio_port_config(struct audio_hw_device *dev,
7712 const struct audio_port_config *config)
7713{
7714 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
7715}
7716
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007717static int adev_dump(const audio_hw_device_t *device __unused,
7718 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007719{
7720 return 0;
7721}
7722
7723static int adev_close(hw_device_t *device)
7724{
Preetam Singh Ranawat624cc802019-06-24 15:11:28 +05307725 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07007726
Preetam Singh Ranawat624cc802019-06-24 15:11:28 +05307727 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07007728 return 0;
7729
7730 pthread_mutex_lock(&adev_init_lock);
7731
7732 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307733 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007734 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08007735 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307736 audio_extn_utils_release_streams_cfg_lists(
7737 &adev->streams_output_cfg_list,
7738 &adev->streams_input_cfg_list);
Sidipotu Ashokafffd202019-05-06 15:41:56 +05307739 if (audio_extn_qap_is_enabled())
7740 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307741 if (audio_extn_qaf_is_enabled())
7742 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007743 audio_route_free(adev->audio_route);
Weiyin Jiang902f7d12019-03-05 23:39:45 +08007744 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07007745 free(adev->snd_dev_ref_cnt);
7746 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007747 if (adev->adm_deinit)
7748 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307749 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007750 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307751 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307752 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007753 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307754 if (adev->device_cfg_params) {
7755 free(adev->device_cfg_params);
7756 adev->device_cfg_params = NULL;
7757 }
Derek Chencdd17c72014-11-24 12:39:14 -08007758 if(adev->ext_hw_plugin)
7759 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Kiran Kandi910e1862013-10-29 13:29:42 -07007760 free(device);
7761 adev = NULL;
7762 }
Balázs Triszka6e101332018-02-26 22:11:10 +01007763
7764 us_deinit();
7765
Kiran Kandi910e1862013-10-29 13:29:42 -07007766 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchaa1358992018-11-14 13:25:08 +05307767 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007768 return 0;
7769}
7770
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007771/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
7772 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
7773 * just that it _might_ work.
7774 */
7775static int period_size_is_plausible_for_low_latency(int period_size)
7776{
7777 switch (period_size) {
7778 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07007779 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007780 case 240:
7781 case 320:
7782 case 480:
7783 return 1;
7784 default:
7785 return 0;
7786 }
7787}
7788
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307789static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
7790{
7791 bool is_snd_card_status = false;
7792 bool is_ext_device_status = false;
7793 char value[32];
7794 int card = -1;
7795 card_status_t status;
7796
7797 if (cookie != adev || !parms)
7798 return;
7799
7800 if (!parse_snd_card_status(parms, &card, &status)) {
7801 is_snd_card_status = true;
7802 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
7803 is_ext_device_status = true;
7804 } else {
7805 // not a valid event
7806 return;
7807 }
7808
7809 pthread_mutex_lock(&adev->lock);
7810 if (card == adev->snd_card || is_ext_device_status) {
7811 if (is_snd_card_status && adev->card_status != status) {
7812 adev->card_status = status;
7813 platform_snd_card_update(adev->platform, status);
7814 audio_extn_fm_set_parameters(adev, parms);
7815 } else if (is_ext_device_status) {
7816 platform_set_parameters(adev->platform, parms);
7817 }
7818 }
7819 pthread_mutex_unlock(&adev->lock);
7820 return;
7821}
7822
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307823/* out and adev lock held */
7824static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
7825{
7826 struct audio_usecase *uc_info;
7827 float left_p;
7828 float right_p;
7829 audio_devices_t devices;
7830
7831 uc_info = get_usecase_from_list(adev, out->usecase);
7832 if (uc_info == NULL) {
7833 ALOGE("%s: Could not find the usecase (%d) in the list",
7834 __func__, out->usecase);
7835 return -EINVAL;
7836 }
7837
7838 ALOGD("%s: enter: usecase(%d: %s)", __func__,
7839 out->usecase, use_case_table[out->usecase]);
7840
7841 if (restore) {
7842 // restore A2DP device for active usecases and unmute if required
7843 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
7844 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
7845 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
7846 select_devices(adev, uc_info->id);
7847 pthread_mutex_lock(&out->compr_mute_lock);
7848 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7849 (out->a2dp_compress_mute)) {
7850 out->a2dp_compress_mute = false;
7851 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
7852 }
7853 pthread_mutex_unlock(&out->compr_mute_lock);
7854 }
7855 } else {
7856 // mute compress stream if suspended
7857 pthread_mutex_lock(&out->compr_mute_lock);
7858 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7859 (!out->a2dp_compress_mute)) {
7860 if (!out->standby) {
7861 ALOGD("%s: selecting speaker and muting stream", __func__);
7862 devices = out->devices;
7863 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
7864 left_p = out->volume_l;
7865 right_p = out->volume_r;
7866 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7867 compress_pause(out->compr);
7868 out_set_compr_volume(&out->stream, (float)0, (float)0);
7869 out->a2dp_compress_mute = true;
7870 select_devices(adev, out->usecase);
7871 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7872 compress_resume(out->compr);
7873 out->devices = devices;
7874 out->volume_l = left_p;
7875 out->volume_r = right_p;
7876 }
7877 }
7878 pthread_mutex_unlock(&out->compr_mute_lock);
7879 }
7880 ALOGV("%s: exit", __func__);
7881 return 0;
7882}
7883
7884int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
7885{
7886 int ret = 0;
7887
7888 lock_output_stream(out);
7889 pthread_mutex_lock(&adev->lock);
7890
7891 ret = check_a2dp_restore_l(adev, out, restore);
7892
7893 pthread_mutex_unlock(&adev->lock);
7894 pthread_mutex_unlock(&out->lock);
7895 return ret;
7896}
7897
Haynes Mathew George01156f92018-04-13 15:29:54 -07007898void adev_on_battery_status_changed(bool charging)
7899{
7900 pthread_mutex_lock(&adev->lock);
7901 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
7902 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08007903 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07007904 pthread_mutex_unlock(&adev->lock);
7905}
7906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007907static int adev_open(const hw_module_t *module, const char *name,
7908 hw_device_t **device)
7909{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307910 int ret;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05307911 char mixer_ctl_name[128] = {0};
7912 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307913
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007914 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007915 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
7916
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007917 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07007918 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007919 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07007920 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007921 ALOGD("%s: returning existing instance of adev", __func__);
7922 ALOGD("%s: exit", __func__);
7923 pthread_mutex_unlock(&adev_init_lock);
7924 return 0;
7925 }
7926
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007927 adev = calloc(1, sizeof(struct audio_device));
7928
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007929 if (!adev) {
7930 pthread_mutex_unlock(&adev_init_lock);
7931 return -ENOMEM;
7932 }
7933
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007934 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
7935
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05307936#ifdef DYNAMIC_LOG_ENABLED
7937 register_for_dynamic_logging("hal");
7938#endif
7939
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007940 adev->device.common.tag = HARDWARE_DEVICE_TAG;
7941 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7942 adev->device.common.module = (struct hw_module_t *)module;
7943 adev->device.common.close = adev_close;
7944
7945 adev->device.init_check = adev_init_check;
7946 adev->device.set_voice_volume = adev_set_voice_volume;
7947 adev->device.set_master_volume = adev_set_master_volume;
7948 adev->device.get_master_volume = adev_get_master_volume;
7949 adev->device.set_master_mute = adev_set_master_mute;
7950 adev->device.get_master_mute = adev_get_master_mute;
7951 adev->device.set_mode = adev_set_mode;
7952 adev->device.set_mic_mute = adev_set_mic_mute;
7953 adev->device.get_mic_mute = adev_get_mic_mute;
7954 adev->device.set_parameters = adev_set_parameters;
7955 adev->device.get_parameters = adev_get_parameters;
7956 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
7957 adev->device.open_output_stream = adev_open_output_stream;
7958 adev->device.close_output_stream = adev_close_output_stream;
7959 adev->device.open_input_stream = adev_open_input_stream;
7960 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307961 adev->device.create_audio_patch = adev_create_audio_patch;
7962 adev->device.release_audio_patch = adev_release_audio_patch;
7963 adev->device.get_audio_port = adev_get_audio_port;
7964 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007965 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307966 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007967
7968 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007969 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08007970 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007971 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007972 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007973 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08007974 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07007975 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307976 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07007977 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07007978 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007979 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08007980 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08007981 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007982 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05307983 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307984 adev->perf_lock_opts[0] = 0x101;
7985 adev->perf_lock_opts[1] = 0x20E;
7986 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007987 adev->dsp_bit_width_enforce_mode = 0;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05307988 adev->use_old_pspd_mix_ctrl = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007990 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07007991 adev->platform = platform_init(adev);
7992 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007993 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007994 free(adev->snd_dev_ref_cnt);
7995 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007996 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07007997 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7998 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08007999 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008000 return -EINVAL;
8001 }
Eric Laurentc4aef752013-09-12 17:45:53 -07008002
Sidipotu Ashokafffd202019-05-06 15:41:56 +05308003 if (audio_extn_qap_is_enabled()) {
8004 ret = audio_extn_qap_init(adev);
8005 if (ret < 0) {
8006 pthread_mutex_destroy(&adev->lock);
8007 free(adev);
8008 adev = NULL;
8009 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8010 *device = NULL;
8011 pthread_mutex_unlock(&adev_init_lock);
8012 return ret;
8013 }
8014 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
8015 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
8016 }
8017
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308018 if (audio_extn_qaf_is_enabled()) {
8019 ret = audio_extn_qaf_init(adev);
8020 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008021 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308022 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008023 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308024 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8025 *device = NULL;
8026 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308027 return ret;
8028 }
8029
8030 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
8031 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
8032 }
8033
Derek Chencdd17c72014-11-24 12:39:14 -08008034 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
8035
Eric Laurentc4aef752013-09-12 17:45:53 -07008036 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
8037 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
8038 if (adev->visualizer_lib == NULL) {
8039 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
8040 } else {
8041 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
8042 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008043 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008044 "visualizer_hal_start_output");
8045 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008046 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008047 "visualizer_hal_stop_output");
8048 }
8049 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05308050 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08008051 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08008052 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308053 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008054 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07008055
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008056 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
8057 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
8058 if (adev->offload_effects_lib == NULL) {
8059 ALOGE("%s: DLOPEN failed for %s", __func__,
8060 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8061 } else {
8062 ALOGV("%s: DLOPEN successful for %s", __func__,
8063 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8064 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05308065 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008066 "offload_effects_bundle_hal_start_output");
8067 adev->offload_effects_stop_output =
8068 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
8069 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008070 adev->offload_effects_set_hpx_state =
8071 (int (*)(bool))dlsym(adev->offload_effects_lib,
8072 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05308073 adev->offload_effects_get_parameters =
8074 (void (*)(struct str_parms *, struct str_parms *))
8075 dlsym(adev->offload_effects_lib,
8076 "offload_effects_bundle_get_parameters");
8077 adev->offload_effects_set_parameters =
8078 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
8079 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008080 }
8081 }
8082
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008083 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
8084 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
8085 if (adev->adm_lib == NULL) {
8086 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
8087 } else {
8088 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
8089 adev->adm_init = (adm_init_t)
8090 dlsym(adev->adm_lib, "adm_init");
8091 adev->adm_deinit = (adm_deinit_t)
8092 dlsym(adev->adm_lib, "adm_deinit");
8093 adev->adm_register_input_stream = (adm_register_input_stream_t)
8094 dlsym(adev->adm_lib, "adm_register_input_stream");
8095 adev->adm_register_output_stream = (adm_register_output_stream_t)
8096 dlsym(adev->adm_lib, "adm_register_output_stream");
8097 adev->adm_deregister_stream = (adm_deregister_stream_t)
8098 dlsym(adev->adm_lib, "adm_deregister_stream");
8099 adev->adm_request_focus = (adm_request_focus_t)
8100 dlsym(adev->adm_lib, "adm_request_focus");
8101 adev->adm_abandon_focus = (adm_abandon_focus_t)
8102 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008103 adev->adm_set_config = (adm_set_config_t)
8104 dlsym(adev->adm_lib, "adm_set_config");
8105 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
8106 dlsym(adev->adm_lib, "adm_request_focus_v2");
8107 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
8108 dlsym(adev->adm_lib, "adm_is_noirq_avail");
8109 adev->adm_on_routing_change = (adm_on_routing_change_t)
8110 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008111 }
8112 }
8113
Mingming Yin514a8bc2014-07-29 15:22:21 -07008114 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008115 //initialize this to false for now,
8116 //this will be set to true through set param
8117 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07008118
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07008119 audio_extn_ds2_enable(adev);
Balázs Triszka6e101332018-02-26 22:11:10 +01008120
8121 us_init(adev);
8122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008123 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008124 adev->dsp_bit_width_enforce_mode =
8125 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008126
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308127 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
8128 &adev->streams_output_cfg_list,
8129 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008130
Kiran Kandi910e1862013-10-29 13:29:42 -07008131 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008132
8133 char value[PROPERTY_VALUE_MAX];
8134 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008135 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008136 trial = atoi(value);
8137 if (period_size_is_plausible_for_low_latency(trial)) {
8138 pcm_config_low_latency.period_size = trial;
8139 pcm_config_low_latency.start_threshold = trial / 4;
8140 pcm_config_low_latency.avail_min = trial / 4;
8141 configured_low_latency_capture_period_size = trial;
8142 }
8143 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008144 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008145 trial = atoi(value);
8146 if (period_size_is_plausible_for_low_latency(trial)) {
8147 configured_low_latency_capture_period_size = trial;
8148 }
8149 }
8150
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08008151 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
8152
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008153 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008154 af_period_multiplier = atoi(value);
8155 if (af_period_multiplier < 0)
8156 af_period_multiplier = 2;
8157 else if (af_period_multiplier > 4)
8158 af_period_multiplier = 4;
8159
8160 ALOGV("new period_multiplier = %d", af_period_multiplier);
8161 }
8162
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008163 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008164 pthread_mutex_unlock(&adev_init_lock);
8165
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008166 if (adev->adm_init)
8167 adev->adm_data = adev->adm_init();
8168
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308169 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308170 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008171 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308172
8173 audio_extn_snd_mon_init();
8174 pthread_mutex_lock(&adev->lock);
8175 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
8176 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07008177 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
8178 /*
8179 * if the battery state callback happens before charging can be queried,
8180 * it will be guarded with the adev->lock held in the cb function and so
8181 * the callback value will reflect the latest state
8182 */
8183 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308184 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08008185 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
8186 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308187 /* Allocate memory for Device config params */
8188 adev->device_cfg_params = (struct audio_device_config_param*)
8189 calloc(platform_get_max_codec_backend(),
8190 sizeof(struct audio_device_config_param));
8191 if (adev->device_cfg_params == NULL)
8192 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308193
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05308194 /*
8195 * Check if new PSPD matrix mixer control is supported. If not
8196 * supported, then set flag so that old mixer ctrl is sent while
8197 * sending pspd coefficients on older kernel version. Query mixer
8198 * control for default pcm id and channel value one.
8199 */
8200 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
8201 "AudStr %d ChMixer Weight Ch %d", 0, 1);
8202
8203 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
8204 if (!ctl) {
8205 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
8206 __func__, mixer_ctl_name);
8207 adev->use_old_pspd_mix_ctrl = true;
8208 }
8209
Eric Laurent994a6932013-07-17 11:51:42 -07008210 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008211 return 0;
8212}
8213
8214static struct hw_module_methods_t hal_module_methods = {
8215 .open = adev_open,
8216};
8217
8218struct audio_module HAL_MODULE_INFO_SYM = {
8219 .common = {
8220 .tag = HARDWARE_MODULE_TAG,
8221 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
8222 .hal_api_version = HARDWARE_HAL_API_VERSION,
8223 .id = AUDIO_HARDWARE_MODULE_ID,
8224 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08008225 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008226 .methods = &hal_module_methods,
8227 },
8228};