blob: e0ab89c7579dc56974d1a3a3d7286cff47874643 [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"
Daniel Hillenbrand53932c92013-05-23 10:10:00 +053079#include "audio_amplifier.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080080
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070081#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080082#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080083
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053084#ifdef DYNAMIC_LOG_ENABLED
85#include <log_xml_parser.h>
86#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
87#include <log_utils.h>
88#endif
89
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070090#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053091/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
92#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070093#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuriebe78a72018-10-04 18:23:46 -070094#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070095#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053096#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070098#define PROXY_OPEN_RETRY_COUNT 100
99#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800100
Mingming Yin08c7e312015-03-16 18:10:58 -0700101#ifdef USE_LL_AS_PRIMARY_OUTPUT
102#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
103#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
104#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800105#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700106#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
107#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800108
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700109#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700110#define DEFAULT_VOIP_BUF_DURATION_MS 20
111#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
112#define DEFAULT_VOIP_SAMP_RATE 48000
113
114#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
115
116struct pcm_config default_pcm_config_voip_copp = {
117 .channels = 1,
118 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
119 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
120 .period_count = 2,
121 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800122 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
123 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700124};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700126#define MIN_CHANNEL_COUNT 1
127#define DEFAULT_CHANNEL_COUNT 2
128#define MAX_HIFI_CHANNEL_COUNT 8
129
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700130static unsigned int configured_low_latency_capture_period_size =
131 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
132
Haynes Mathew George16081042017-05-31 17:16:49 -0700133#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
134#define MMAP_PERIOD_COUNT_MIN 32
135#define MMAP_PERIOD_COUNT_MAX 512
136#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
137
Eric Laurentb23d5282013-05-14 15:27:20 -0700138struct pcm_config pcm_config_deep_buffer = {
139 .channels = 2,
140 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
141 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
142 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
143 .format = PCM_FORMAT_S16_LE,
144 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
145 .stop_threshold = INT_MAX,
146 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
147};
148
149struct pcm_config pcm_config_low_latency = {
150 .channels = 2,
151 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
152 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
153 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
154 .format = PCM_FORMAT_S16_LE,
155 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
156 .stop_threshold = INT_MAX,
157 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
158};
159
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700160static int af_period_multiplier = 4;
161struct pcm_config pcm_config_rt = {
162 .channels = 2,
163 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
164 .period_size = ULL_PERIOD_SIZE, //1 ms
165 .period_count = 512, //=> buffer size is 512ms
166 .format = PCM_FORMAT_S16_LE,
167 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
168 .stop_threshold = INT_MAX,
169 .silence_threshold = 0,
170 .silence_size = 0,
171 .avail_min = ULL_PERIOD_SIZE, //1 ms
172};
173
Eric Laurentb23d5282013-05-14 15:27:20 -0700174struct pcm_config pcm_config_hdmi_multi = {
175 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
176 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
177 .period_size = HDMI_MULTI_PERIOD_SIZE,
178 .period_count = HDMI_MULTI_PERIOD_COUNT,
179 .format = PCM_FORMAT_S16_LE,
180 .start_threshold = 0,
181 .stop_threshold = INT_MAX,
182 .avail_min = 0,
183};
184
Haynes Mathew George16081042017-05-31 17:16:49 -0700185struct pcm_config pcm_config_mmap_playback = {
186 .channels = 2,
187 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
188 .period_size = MMAP_PERIOD_SIZE,
189 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
190 .format = PCM_FORMAT_S16_LE,
191 .start_threshold = MMAP_PERIOD_SIZE*8,
192 .stop_threshold = INT32_MAX,
193 .silence_threshold = 0,
194 .silence_size = 0,
195 .avail_min = MMAP_PERIOD_SIZE, //1 ms
196};
197
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700198struct pcm_config pcm_config_hifi = {
199 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
200 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
201 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
202 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
203 .format = PCM_FORMAT_S24_3LE,
204 .start_threshold = 0,
205 .stop_threshold = INT_MAX,
206 .avail_min = 0,
207};
208
Eric Laurentb23d5282013-05-14 15:27:20 -0700209struct pcm_config pcm_config_audio_capture = {
210 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700211 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
212 .format = PCM_FORMAT_S16_LE,
213};
214
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700215struct pcm_config pcm_config_audio_capture_rt = {
216 .channels = 2,
217 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
218 .period_size = ULL_PERIOD_SIZE,
219 .period_count = 512,
220 .format = PCM_FORMAT_S16_LE,
221 .start_threshold = 0,
222 .stop_threshold = INT_MAX,
223 .silence_threshold = 0,
224 .silence_size = 0,
225 .avail_min = ULL_PERIOD_SIZE, //1 ms
226};
227
Haynes Mathew George16081042017-05-31 17:16:49 -0700228struct pcm_config pcm_config_mmap_capture = {
229 .channels = 2,
230 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
231 .period_size = MMAP_PERIOD_SIZE,
232 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
233 .format = PCM_FORMAT_S16_LE,
234 .start_threshold = 0,
235 .stop_threshold = INT_MAX,
236 .silence_threshold = 0,
237 .silence_size = 0,
238 .avail_min = MMAP_PERIOD_SIZE, //1 ms
239};
240
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700241#define AFE_PROXY_CHANNEL_COUNT 2
242#define AFE_PROXY_SAMPLING_RATE 48000
243
244#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
245#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
246
247struct pcm_config pcm_config_afe_proxy_playback = {
248 .channels = AFE_PROXY_CHANNEL_COUNT,
249 .rate = AFE_PROXY_SAMPLING_RATE,
250 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
251 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
252 .format = PCM_FORMAT_S16_LE,
253 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
254 .stop_threshold = INT_MAX,
255 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
256};
257
258#define AFE_PROXY_RECORD_PERIOD_SIZE 768
259#define AFE_PROXY_RECORD_PERIOD_COUNT 4
260
261struct pcm_config pcm_config_afe_proxy_record = {
262 .channels = AFE_PROXY_CHANNEL_COUNT,
263 .rate = AFE_PROXY_SAMPLING_RATE,
264 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
265 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
266 .format = PCM_FORMAT_S16_LE,
267 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
268 .stop_threshold = INT_MAX,
269 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
270};
271
Ashish Jainf1eaa582016-05-23 20:54:24 +0530272#define AUDIO_MAX_PCM_FORMATS 7
273
274const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
275 [AUDIO_FORMAT_DEFAULT] = 0,
276 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
277 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
278 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
279 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
280 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
281 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
282};
283
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800284const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700285 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
286 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700287 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
288 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700289 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700290 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700291 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
292 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
293 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
294 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
295 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
296 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
297 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
298 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700299 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
300 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700301 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700302
Eric Laurentb23d5282013-05-14 15:27:20 -0700303 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700304 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530305 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
306 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
307 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530308 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
309 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700310 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700311 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700312 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700313 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700314
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800315 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800316 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700317 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700318
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700319 [USECASE_VOICE2_CALL] = "voice2-call",
320 [USECASE_VOLTE_CALL] = "volte-call",
321 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800322 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800323 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
324 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800325 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700326 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
327 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
328 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800329 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
330 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
331 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
332
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700333 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
334 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700335 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
336 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700337
338 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
339 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530340 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700341
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530342 /* Transcode loopback cases */
343 [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700344
345 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
346 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530347 /* For Interactive Audio Streams */
348 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
349 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
350 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
351 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
352 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
353 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
354 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
355 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700356
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800357 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
358
Balázs Triszka6e101332018-02-26 22:11:10 +0100359 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
360
361 /* For Elliptic Ultrasound proximity sensor */
362 [USECASE_AUDIO_ULTRASOUND_RX] = "ultrasound-rx",
363 [USECASE_AUDIO_ULTRASOUND_TX] = "ultrasound-tx",
Eric Laurentb23d5282013-05-14 15:27:20 -0700364};
365
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700366static const audio_usecase_t offload_usecases[] = {
367 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700368 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
369 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
370 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
371 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
372 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
373 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
374 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
375 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700376};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800377
Varun Balaraje49253e2017-07-06 19:48:56 +0530378static const audio_usecase_t interactive_usecases[] = {
379 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
380 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
381 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
382 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
383 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
384 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
385 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
386 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
387};
388
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800389#define STRING_TO_ENUM(string) { #string, string }
390
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800391struct string_to_enum {
392 const char *name;
393 uint32_t value;
394};
395
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700396static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800397 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800398 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
399 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
400 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700401 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800402 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
403 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800404 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700405 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
406 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
407 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
408 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
409 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
410 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
411 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
412 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
413 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
414 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
415 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800416};
417
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700418static const struct string_to_enum formats_name_to_enum_table[] = {
419 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
420 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
421 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700422 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
423 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
424 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700425 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800426 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
427 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700428 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800429};
430
431//list of all supported sample rates by HDMI specification.
432static const int out_hdmi_sample_rates[] = {
433 32000, 44100, 48000, 88200, 96000, 176400, 192000,
434};
435
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700436static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800437 STRING_TO_ENUM(32000),
438 STRING_TO_ENUM(44100),
439 STRING_TO_ENUM(48000),
440 STRING_TO_ENUM(88200),
441 STRING_TO_ENUM(96000),
442 STRING_TO_ENUM(176400),
443 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700444};
445
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700446static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700447static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700448static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700449//cache last MBDRC cal step level
450static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700451
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530452static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
453static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuriebe78a72018-10-04 18:23:46 -0700454static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800455static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530456
Vatsal Buchaa1358992018-11-14 13:25:08 +0530457#ifdef AUDIO_FEATURE_ENABLED_GCOV
458extern void __gcov_flush();
459static void enable_gcov()
460{
461 __gcov_flush();
462}
463#else
464static void enable_gcov()
465{
466}
467#endif
468
Ramjee Singhacef98f2019-06-28 11:01:25 +0530469#if ANDROID_PLATFORM_SDK_VERSION >= 29
470static int in_set_microphone_direction(const struct audio_stream_in *stream,
471 audio_microphone_direction_t dir);
472static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
473#endif
474
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700475static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
476 int flags __unused)
477{
478 int dir = 0;
479 switch (uc_id) {
480 case USECASE_AUDIO_RECORD_LOW_LATENCY:
481 dir = 1;
482 case USECASE_AUDIO_PLAYBACK_ULL:
483 break;
484 default:
485 return false;
486 }
487
488 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
489 PCM_PLAYBACK : PCM_CAPTURE);
490 if (adev->adm_is_noirq_avail)
491 return adev->adm_is_noirq_avail(adev->adm_data,
492 adev->snd_card, dev_id, dir);
493 return false;
494}
495
496static void register_out_stream(struct stream_out *out)
497{
498 struct audio_device *adev = out->dev;
499 if (is_offload_usecase(out->usecase) ||
500 !adev->adm_register_output_stream)
501 return;
502
503 // register stream first for backward compatibility
504 adev->adm_register_output_stream(adev->adm_data,
505 out->handle,
506 out->flags);
507
508 if (!adev->adm_set_config)
509 return;
510
511 if (out->realtime)
512 adev->adm_set_config(adev->adm_data,
513 out->handle,
514 out->pcm, &out->config);
515}
516
517static void register_in_stream(struct stream_in *in)
518{
519 struct audio_device *adev = in->dev;
520 if (!adev->adm_register_input_stream)
521 return;
522
523 adev->adm_register_input_stream(adev->adm_data,
524 in->capture_handle,
525 in->flags);
526
527 if (!adev->adm_set_config)
528 return;
529
530 if (in->realtime)
531 adev->adm_set_config(adev->adm_data,
532 in->capture_handle,
533 in->pcm,
534 &in->config);
535}
536
537static void request_out_focus(struct stream_out *out, long ns)
538{
539 struct audio_device *adev = out->dev;
540
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700541 if (adev->adm_request_focus_v2)
542 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
543 else if (adev->adm_request_focus)
544 adev->adm_request_focus(adev->adm_data, out->handle);
545}
546
547static void request_in_focus(struct stream_in *in, long ns)
548{
549 struct audio_device *adev = in->dev;
550
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700551 if (adev->adm_request_focus_v2)
552 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
553 else if (adev->adm_request_focus)
554 adev->adm_request_focus(adev->adm_data, in->capture_handle);
555}
556
557static void release_out_focus(struct stream_out *out)
558{
559 struct audio_device *adev = out->dev;
560
561 if (adev->adm_abandon_focus)
562 adev->adm_abandon_focus(adev->adm_data, out->handle);
563}
564
565static void release_in_focus(struct stream_in *in)
566{
567 struct audio_device *adev = in->dev;
568 if (adev->adm_abandon_focus)
569 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
570}
571
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530572static int parse_snd_card_status(struct str_parms *parms, int *card,
573 card_status_t *status)
574{
575 char value[32]={0};
576 char state[32]={0};
577
578 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
579 if (ret < 0)
580 return -1;
581
582 // sscanf should be okay as value is of max length 32.
583 // same as sizeof state.
584 if (sscanf(value, "%d,%s", card, state) < 2)
585 return -1;
586
587 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
588 CARD_STATUS_OFFLINE;
589 return 0;
590}
591
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700592static inline void adjust_frames_for_device_delay(struct stream_out *out,
593 uint32_t *dsp_frames) {
594 // Adjustment accounts for A2dp encoder latency with offload usecases
595 // Note: Encoder latency is returned in ms.
596 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
597 unsigned long offset =
598 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
599 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
600 }
601}
602
vivek mehtaa76401a2015-04-24 14:12:15 -0700603__attribute__ ((visibility ("default")))
604bool audio_hw_send_gain_dep_calibration(int level) {
605 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700606 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700607
608 pthread_mutex_lock(&adev_init_lock);
609
610 if (adev != NULL && adev->platform != NULL) {
611 pthread_mutex_lock(&adev->lock);
612 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700613
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530614 // cache level info for any of the use case which
615 // was not started.
616 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700617
vivek mehtaa76401a2015-04-24 14:12:15 -0700618 pthread_mutex_unlock(&adev->lock);
619 } else {
620 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
621 }
622
623 pthread_mutex_unlock(&adev_init_lock);
624
625 return ret_val;
626}
627
Ashish Jain5106d362016-05-11 19:23:33 +0530628static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
629{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800630 bool gapless_enabled = false;
631 const char *mixer_ctl_name = "Compress Gapless Playback";
632 struct mixer_ctl *ctl;
633
634 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700635 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530636
637 /*Disable gapless if its AV playback*/
638 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800639
640 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
641 if (!ctl) {
642 ALOGE("%s: Could not get ctl for mixer cmd - %s",
643 __func__, mixer_ctl_name);
644 return -EINVAL;
645 }
646
647 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
648 ALOGE("%s: Could not set gapless mode %d",
649 __func__, gapless_enabled);
650 return -EINVAL;
651 }
652 return 0;
653}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700654
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700655__attribute__ ((visibility ("default")))
656int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
657 int table_size) {
658 int ret_val = 0;
659 ALOGV("%s: enter ... ", __func__);
660
661 pthread_mutex_lock(&adev_init_lock);
662 if (adev == NULL) {
663 ALOGW("%s: adev is NULL .... ", __func__);
664 goto done;
665 }
666
667 pthread_mutex_lock(&adev->lock);
668 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
669 pthread_mutex_unlock(&adev->lock);
670done:
671 pthread_mutex_unlock(&adev_init_lock);
672 ALOGV("%s: exit ... ", __func__);
673 return ret_val;
674}
675
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700676static bool is_supported_format(audio_format_t format)
677{
Eric Laurent86e17132013-09-12 17:49:30 -0700678 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530679 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530680 format == AUDIO_FORMAT_AAC_LC ||
681 format == AUDIO_FORMAT_AAC_HE_V1 ||
682 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530683 format == AUDIO_FORMAT_AAC_ADTS_LC ||
684 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
685 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530686 format == AUDIO_FORMAT_AAC_LATM_LC ||
687 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
688 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530689 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
690 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530691 format == AUDIO_FORMAT_PCM_FLOAT ||
692 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700693 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530694 format == AUDIO_FORMAT_AC3 ||
695 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700696 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530697 format == AUDIO_FORMAT_DTS ||
698 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800699 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530700 format == AUDIO_FORMAT_ALAC ||
701 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530702 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530703 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800704 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530705 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700706 format == AUDIO_FORMAT_APTX ||
707 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800708 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700709
710 return false;
711}
712
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700713static inline bool is_mmap_usecase(audio_usecase_t uc_id)
714{
715 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
716 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
717}
718
Avinash Vaish71a8b972014-07-24 15:36:33 +0530719static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
720 struct audio_usecase *uc_info)
721{
722 struct listnode *node;
723 struct audio_usecase *usecase;
724
725 if (uc_info == NULL)
726 return -EINVAL;
727
728 /* Re-route all voice usecases on the shared backend other than the
729 specified usecase to new snd devices */
730 list_for_each(node, &adev->usecase_list) {
731 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800732 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530733 enable_audio_route(adev, usecase);
734 }
735 return 0;
736}
737
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530738static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530739{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530740 ALOGV("%s", __func__);
741 audio_route_apply_and_update_path(adev->audio_route,
742 "asrc-mode");
743 adev->asrc_mode_enabled = true;
744}
745
746static void disable_asrc_mode(struct audio_device *adev)
747{
748 ALOGV("%s", __func__);
749 audio_route_reset_and_update_path(adev->audio_route,
750 "asrc-mode");
751 adev->asrc_mode_enabled = false;
752}
753
754/*
755 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
756 * 44.1 or Native DSD backends are enabled for any of current use case.
757 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
758 * - Disable current mix path use case(Headphone backend) and re-enable it with
759 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
760 * e.g. Naitve DSD or Headphone 44.1 -> + 48
761 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530762static void check_and_set_asrc_mode(struct audio_device *adev,
763 struct audio_usecase *uc_info,
764 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530765{
766 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530767 int i, num_new_devices = 0;
768 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
769 /*
770 *Split snd device for new combo use case
771 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
772 */
773 if (platform_split_snd_device(adev->platform,
774 snd_device,
775 &num_new_devices,
776 split_new_snd_devices) == 0) {
777 for (i = 0; i < num_new_devices; i++)
778 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
779 } else {
780 int new_backend_idx = platform_get_backend_index(snd_device);
781 if (((new_backend_idx == HEADPHONE_BACKEND) ||
782 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
783 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
784 !adev->asrc_mode_enabled) {
785 struct listnode *node = NULL;
786 struct audio_usecase *uc = NULL;
787 struct stream_out *curr_out = NULL;
788 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
789 int i, num_devices, ret = 0;
790 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530791
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530792 list_for_each(node, &adev->usecase_list) {
793 uc = node_to_item(node, struct audio_usecase, list);
794 curr_out = (struct stream_out*) uc->stream.out;
795 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
796 /*
797 *Split snd device for existing combo use case
798 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
799 */
800 ret = platform_split_snd_device(adev->platform,
801 uc->out_snd_device,
802 &num_devices,
803 split_snd_devices);
804 if (ret < 0 || num_devices == 0) {
805 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
806 split_snd_devices[0] = uc->out_snd_device;
807 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800808 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530809 for (i = 0; i < num_devices; i++) {
810 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
811 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
812 if((new_backend_idx == HEADPHONE_BACKEND) &&
813 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
814 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
815 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
816 __func__);
817 enable_asrc_mode(adev);
818 break;
819 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
820 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
821 (usecase_backend_idx == HEADPHONE_BACKEND)) {
822 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
823 __func__);
824 disable_audio_route(adev, uc);
825 disable_snd_device(adev, uc->out_snd_device);
826 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
827 if (new_backend_idx == DSD_NATIVE_BACKEND)
828 audio_route_apply_and_update_path(adev->audio_route,
829 "hph-true-highquality-mode");
830 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
831 (curr_out->bit_width >= 24))
832 audio_route_apply_and_update_path(adev->audio_route,
833 "hph-highquality-mode");
834 enable_asrc_mode(adev);
835 enable_snd_device(adev, uc->out_snd_device);
836 enable_audio_route(adev, uc);
837 break;
838 }
839 }
840 // reset split devices count
841 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800842 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530843 if (adev->asrc_mode_enabled)
844 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530845 }
846 }
847 }
848}
849
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700850#ifdef DYNAMIC_ECNS_ENABLED
851static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
852 struct audio_effect_config effect_config,
853 unsigned int param_value)
854{
855 char mixer_ctl_name[] = "Audio Effect";
856 struct mixer_ctl *ctl;
857 long set_values[6];
858 struct stream_in *in = adev->active_input;
859
860 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
861 if (!ctl) {
862 ALOGE("%s: Could not get mixer ctl - %s",
863 __func__, mixer_ctl_name);
864 return -EINVAL;
865 }
866
867 set_values[0] = 1; //0:Rx 1:Tx
868 set_values[1] = in->app_type_cfg.app_type;
869 set_values[2] = (long)effect_config.module_id;
870 set_values[3] = (long)effect_config.instance_id;
871 set_values[4] = (long)effect_config.param_id;
872 set_values[5] = param_value;
873
874 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
875
876 return 0;
877
878}
879
880static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
881 int effect_type, unsigned int *param_value)
882{
883 int ret = 0;
884 struct audio_effect_config other_effect_config;
885 struct audio_usecase *usecase = NULL;
886 struct stream_in *in = adev->active_input;
887
888 usecase = get_usecase_from_list(adev, in->usecase);
889 if (!usecase)
890 return -EINVAL;
891
892 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
893 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
894 if (ret < 0) {
895 ALOGE("%s Failed to get effect params %d", __func__, ret);
896 return ret;
897 }
898
899 if (module_id == other_effect_config.module_id) {
900 //Same module id for AEC/NS. Values need to be combined
901 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
902 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
903 *param_value |= other_effect_config.param_value;
904 }
905 }
906
907 return ret;
908}
909
910static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
911{
912 struct audio_effect_config effect_config;
913 struct audio_usecase *usecase = NULL;
914 int ret = 0;
915 unsigned int param_value = 0;
916 struct stream_in *in = adev->active_input;
917
918 if (!in) {
919 ALOGE("%s: Invalid input stream", __func__);
920 return -EINVAL;
921 }
922
923 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
924
925 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800926 if (usecase == NULL) {
927 ALOGE("%s: Could not find the usecase (%d) in the list",
928 __func__, in->usecase);
929 return -EINVAL;
930 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700931
932 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
933 if (ret < 0) {
934 ALOGE("%s Failed to get module id %d", __func__, ret);
935 return ret;
936 }
937 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
938 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
939
940 if(enable)
941 param_value = effect_config.param_value;
942
943 /*Special handling for AEC & NS effects Param values need to be
944 updated if module ids are same*/
945
946 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
947 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
948 if (ret < 0)
949 return ret;
950 }
951
952 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
953
954 return ret;
955}
956
957static void check_and_enable_effect(struct audio_device *adev)
958{
959
960 if (adev->active_input->enable_aec) {
961 enable_disable_effect(adev, EFFECT_AEC, true);
962 }
963
964 if (adev->active_input->enable_ns &&
965 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
966 enable_disable_effect(adev, EFFECT_NS, true);
967 }
968}
969#else
970#define enable_disable_effect(x, y, z) ENOSYS
971#define check_and_enable_effect(x) ENOSYS
972#endif
973
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700974int pcm_ioctl(struct pcm *pcm, int request, ...)
975{
976 va_list ap;
977 void * arg;
978 int pcm_fd = *(int*)pcm;
979
980 va_start(ap, request);
981 arg = va_arg(ap, void *);
982 va_end(ap);
983
984 return ioctl(pcm_fd, request, arg);
985}
986
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700987int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700988 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800989{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700990 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700991 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530992 struct stream_out *out = NULL;
Soumya Managolie7651c42018-06-28 16:04:57 +0530993 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800994
995 if (usecase == NULL)
996 return -EINVAL;
997
998 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
999
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001000 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001001 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001002 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001003 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001004
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001005#ifdef DS1_DOLBY_DAP_ENABLED
1006 audio_extn_dolby_set_dmid(adev);
1007 audio_extn_dolby_set_endpoint(adev);
1008#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001009 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001010 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301011 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001012 audio_extn_utils_send_app_type_cfg(adev, usecase);
Balázs Triszka6e101332018-02-26 22:11:10 +01001013#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1014 if (usecase->id != USECASE_AUDIO_ULTRASOUND_TX)
1015#endif
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301016 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301017 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1018 out = usecase->stream.out;
1019 if (out && out->compr)
1020 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1021 }
Dhananjay Kumar2a7f75b2018-12-10 22:26:53 +05301022 audio_extn_set_custom_mtmx_params(adev, usecase, true);
Manish Dewangan58229382017-02-02 15:48:41 +05301023
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001024 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001025 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001026 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managolie7651c42018-06-28 16:04:57 +05301027 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1028 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1029 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1030 if (parms) {
1031 audio_extn_fm_set_parameters(adev, parms);
1032 str_parms_destroy(parms);
1033 }
1034 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001035 ALOGV("%s: exit", __func__);
1036 return 0;
1037}
1038
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001039int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001040 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001041{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001042 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001043 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001044
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301045 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001046 return -EINVAL;
1047
1048 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049 if (usecase->type == PCM_CAPTURE)
1050 snd_device = usecase->in_snd_device;
1051 else
1052 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001053 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001054 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001055 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001056 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001057 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301058 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Dhananjay Kumar2a7f75b2018-12-10 22:26:53 +05301059 audio_extn_set_custom_mtmx_params(adev, usecase, false);
Weiyin Jiange2938532019-06-03 14:29:30 +08001060 if ((usecase->type == PCM_PLAYBACK) &&
1061 (usecase->stream.out != NULL))
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05301062 usecase->stream.out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063 ALOGV("%s: exit", __func__);
1064 return 0;
1065}
1066
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001067int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001068 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001069{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301070 int i, num_devices = 0;
1071 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001072 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1073
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001074 if (snd_device < SND_DEVICE_MIN ||
1075 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001076 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001077 return -EINVAL;
1078 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001079
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001080 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001081 ALOGE("%s: Invalid sound device returned", __func__);
1082 return -EINVAL;
1083 }
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001084
1085 adev->snd_dev_ref_cnt[snd_device]++;
1086
1087 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1088 (platform_split_snd_device(adev->platform,
1089 snd_device,
1090 &num_devices,
1091 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001092 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001093 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001094 return 0;
1095 }
1096
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001097 if (audio_extn_spkr_prot_is_enabled())
1098 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001099
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001100 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1101 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001102 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1103 goto err;
1104 }
1105 audio_extn_dev_arbi_acquire(snd_device);
1106 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001107 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001108 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001109 goto err;
1110 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001111 } else if (platform_split_snd_device(adev->platform,
1112 snd_device,
1113 &num_devices,
1114 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301115 for (i = 0; i < num_devices; i++) {
1116 enable_snd_device(adev, new_snd_devices[i]);
1117 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001118 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001119 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301120
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301121
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001122 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1123 (audio_extn_a2dp_start_playback() < 0)) {
1124 ALOGE(" fail to configure A2dp control path ");
1125 goto err;
1126 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301127
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001128 /* due to the possibility of calibration overwrite between listen
1129 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001130 audio_extn_sound_trigger_update_device_status(snd_device,
1131 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301132 audio_extn_listen_update_device_status(snd_device,
1133 LISTEN_EVENT_SND_DEVICE_BUSY);
Balázs Triszka6e101332018-02-26 22:11:10 +01001134#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1135 if (snd_device != SND_DEVICE_OUT_ULTRASOUND_HANDSET &&
1136 snd_device != SND_DEVICE_IN_ULTRASOUND_MIC)
1137#endif
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001138 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001139 audio_extn_sound_trigger_update_device_status(snd_device,
1140 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301141 audio_extn_listen_update_device_status(snd_device,
1142 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001143 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001144 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001145 audio_extn_dev_arbi_acquire(snd_device);
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05301146 amplifier_enable_devices(snd_device, true);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001147 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301148
1149 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1150 !adev->native_playback_enabled &&
1151 audio_is_true_native_stream_active(adev)) {
1152 ALOGD("%s: %d: napb: enabling native mode in hardware",
1153 __func__, __LINE__);
1154 audio_route_apply_and_update_path(adev->audio_route,
1155 "true-native-mode");
1156 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301157 }
Dhanalakshmi Siddani0f1dfd52019-01-09 12:38:13 +05301158 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1159 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001160 (audio_extn_ffv_get_stream() == adev->active_input)) {
1161 ALOGD("%s: init ec ref loopback", __func__);
1162 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1163 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001164 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001165 return 0;
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001166err:
1167 adev->snd_dev_ref_cnt[snd_device]--;
1168 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001169}
1170
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001171int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001172 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001173{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301174 int i, num_devices = 0;
1175 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001176 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1177
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001178 if (snd_device < SND_DEVICE_MIN ||
1179 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001180 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001181 return -EINVAL;
1182 }
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001183
1184 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1185 ALOGE("%s: Invalid sound device returned", __func__);
1186 return -EINVAL;
1187 }
1188
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001189 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1190 ALOGE("%s: device ref cnt is already 0", __func__);
1191 return -EINVAL;
1192 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001193
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001194 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001195
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001196 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001197 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301198
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001199 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1200 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001201 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001202
1203 // when speaker device is disabled, reset swap.
1204 // will be renabled on usecase start
1205 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001206 } else if (platform_split_snd_device(adev->platform,
1207 snd_device,
1208 &num_devices,
1209 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301210 for (i = 0; i < num_devices; i++) {
1211 disable_snd_device(adev, new_snd_devices[i]);
1212 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001213 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001214 audio_route_reset_and_update_path(adev->audio_route, device_name);
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05301215 amplifier_enable_devices(snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001216 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001217
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301218 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1219 audio_extn_a2dp_stop_playback();
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001220 else if (snd_device == SND_DEVICE_OUT_HDMI ||
1221 snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301222 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301223 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001224 adev->native_playback_enabled) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301225 ALOGD("%s: %d: napb: disabling native mode in hardware",
1226 __func__, __LINE__);
1227 audio_route_reset_and_update_path(adev->audio_route,
1228 "true-native-mode");
1229 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301230 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001231 adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301232 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301233 disable_asrc_mode(adev);
1234 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001235 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1236 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
1237 (audio_extn_ffv_get_stream() == adev->active_input)) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001238 ALOGD("%s: deinit ec ref loopback", __func__);
1239 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1240 }
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001241
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001242 audio_extn_utils_release_snd_device(snd_device);
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001243 } else {
1244 if (platform_split_snd_device(adev->platform,
1245 snd_device,
1246 &num_devices,
1247 new_snd_devices) == 0) {
1248 for (i = 0; i < num_devices; i++) {
1249 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1250 }
1251 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001252 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001253
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001254 return 0;
1255}
1256
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001257/*
1258 legend:
1259 uc - existing usecase
1260 new_uc - new usecase
1261 d1, d11, d2 - SND_DEVICE enums
1262 a1, a2 - corresponding ANDROID device enums
1263 B1, B2 - backend strings
1264
1265case 1
1266 uc->dev d1 (a1) B1
1267 new_uc->dev d1 (a1), d2 (a2) B1, B2
1268
1269 resolution: disable and enable uc->dev on d1
1270
1271case 2
1272 uc->dev d1 (a1) B1
1273 new_uc->dev d11 (a1) B1
1274
1275 resolution: need to switch uc since d1 and d11 are related
1276 (e.g. speaker and voice-speaker)
1277 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1278
1279case 3
1280 uc->dev d1 (a1) B1
1281 new_uc->dev d2 (a2) B2
1282
1283 resolution: no need to switch uc
1284
1285case 4
1286 uc->dev d1 (a1) B1
1287 new_uc->dev d2 (a2) B1
1288
1289 resolution: disable enable uc-dev on d2 since backends match
1290 we cannot enable two streams on two different devices if they
1291 share the same backend. e.g. if offload is on speaker device using
1292 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1293 using the same backend, offload must also be switched to voice-handset.
1294
1295case 5
1296 uc->dev d1 (a1) B1
1297 new_uc->dev d1 (a1), d2 (a2) B1
1298
1299 resolution: disable enable uc-dev on d2 since backends match
1300 we cannot enable two streams on two different devices if they
1301 share the same backend.
1302
1303case 6
1304 uc->dev d1 (a1) B1
1305 new_uc->dev d2 (a1) B2
1306
1307 resolution: no need to switch
1308
1309case 7
1310 uc->dev d1 (a1), d2 (a2) B1, B2
1311 new_uc->dev d1 (a1) B1
1312
1313 resolution: no need to switch
1314
Zhou Song4ba65882018-07-09 14:48:07 +08001315case 8
1316 uc->dev d1 (a1) B1
1317 new_uc->dev d11 (a1), d2 (a2) B1, B2
1318 resolution: compared to case 1, for this case, d1 and d11 are related
1319 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001320*/
1321static snd_device_t derive_playback_snd_device(void * platform,
1322 struct audio_usecase *uc,
1323 struct audio_usecase *new_uc,
1324 snd_device_t new_snd_device)
1325{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301326 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001327
1328 snd_device_t d1 = uc->out_snd_device;
1329 snd_device_t d2 = new_snd_device;
1330
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301331 switch (uc->type) {
1332 case TRANSCODE_LOOPBACK :
1333 a1 = uc->stream.inout->out_config.devices;
1334 a2 = new_uc->stream.inout->out_config.devices;
1335 break;
1336 default :
1337 a1 = uc->stream.out->devices;
1338 a2 = new_uc->stream.out->devices;
1339 break;
1340 }
1341
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001342 // Treat as a special case when a1 and a2 are not disjoint
1343 if ((a1 != a2) && (a1 & a2)) {
1344 snd_device_t d3[2];
1345 int num_devices = 0;
1346 int ret = platform_split_snd_device(platform,
1347 popcount(a1) > 1 ? d1 : d2,
1348 &num_devices,
1349 d3);
1350 if (ret < 0) {
1351 if (ret != -ENOSYS) {
1352 ALOGW("%s failed to split snd_device %d",
1353 __func__,
1354 popcount(a1) > 1 ? d1 : d2);
1355 }
1356 goto end;
1357 }
1358
1359 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1360 // But if it does happen, we need to give priority to d2 if
1361 // the combo devices active on the existing usecase share a backend.
1362 // This is because we cannot have a usecase active on a combo device
1363 // and a new usecase requests one device in this combo pair.
1364 if (platform_check_backends_match(d3[0], d3[1])) {
1365 return d2; // case 5
1366 } else {
Zhou Song671be042018-08-27 15:33:52 +08001367 // check if d1 is related to any of d3's OR
1368 // old uc is combo device but new_uc is one of the combo device
1369 if (d1 == d3[0] || d1 == d3[1] || popcount(a1) > 1)
1370 return d1; // case 1, 7
Zhou Song4ba65882018-07-09 14:48:07 +08001371 else
1372 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001373 }
1374 } else {
1375 if (platform_check_backends_match(d1, d2)) {
1376 return d2; // case 2, 4
1377 } else {
1378 return d1; // case 6, 3
1379 }
1380 }
1381
1382end:
1383 return d2; // return whatever was calculated before.
1384}
1385
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001386static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301387 struct audio_usecase *uc_info,
1388 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001389{
1390 struct listnode *node;
1391 struct audio_usecase *usecase;
1392 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301393 snd_device_t uc_derive_snd_device;
1394 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001395 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1396 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001397 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301398 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001399 /*
1400 * This function is to make sure that all the usecases that are active on
1401 * the hardware codec backend are always routed to any one device that is
1402 * handled by the hardware codec.
1403 * For example, if low-latency and deep-buffer usecases are currently active
1404 * on speaker and out_set_parameters(headset) is received on low-latency
1405 * output, then we have to make sure deep-buffer is also switched to headset,
1406 * because of the limitation that both the devices cannot be enabled
1407 * at the same time as they share the same backend.
1408 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001409 /*
1410 * This call is to check if we need to force routing for a particular stream
1411 * If there is a backend configuration change for the device when a
1412 * new stream starts, then ADM needs to be closed and re-opened with the new
1413 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001414 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001415 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001416 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1417 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301418 /* For a2dp device reconfigure all active sessions
1419 * with new AFE encoder format based on a2dp state
1420 */
1421 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1422 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1423 audio_extn_a2dp_is_force_device_switch()) {
1424 force_routing = true;
1425 force_restart_session = true;
1426 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301427 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1428
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001429 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001430 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001431 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001432 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1433 switch_device[i] = false;
1434
1435 list_for_each(node, &adev->usecase_list) {
1436 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001437
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301438 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1439 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301440 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301441 platform_get_snd_device_name(usecase->out_snd_device),
1442 platform_check_backends_match(snd_device, usecase->out_snd_device));
Balázs Triszka6e101332018-02-26 22:11:10 +01001443
1444#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1445 if (usecase->id == USECASE_AUDIO_ULTRASOUND_RX)
1446 continue;
1447#endif
1448
Ashish Jain6a65b352017-03-21 17:24:40 +05301449 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1450 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1451 usecase, uc_info, snd_device);
1452 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1453 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1454 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1455 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001456 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301457 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1458 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1459 ((force_restart_session) ||
1460 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301461 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1462 __func__, use_case_table[usecase->id],
1463 platform_get_snd_device_name(usecase->out_snd_device));
1464 disable_audio_route(adev, usecase);
1465 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301466 /* Enable existing usecase on derived playback device */
1467 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301468 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301469 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001470 }
1471 }
1472
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301473 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1474 num_uc_to_switch);
1475
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001476 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001477 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001478
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301479 /* Make sure the previous devices to be disabled first and then enable the
1480 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001481 list_for_each(node, &adev->usecase_list) {
1482 usecase = node_to_item(node, struct audio_usecase, list);
1483 if (switch_device[usecase->id]) {
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001484 /* Check if output sound device to be switched can be split and if any
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001485 of the split devices match with derived sound device */
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001486 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1487 &num_devices, split_snd_devices) == 0) {
1488 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001489 for (i = 0; i < num_devices; i++) {
1490 /* Disable devices that do not match with derived sound device */
1491 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1492 disable_snd_device(adev, split_snd_devices[i]);
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001493 }
1494 } else {
1495 disable_snd_device(adev, usecase->out_snd_device);
1496 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001497 }
1498 }
1499
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001500 list_for_each(node, &adev->usecase_list) {
1501 usecase = node_to_item(node, struct audio_usecase, list);
1502 if (switch_device[usecase->id]) {
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001503 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1504 &num_devices, split_snd_devices) == 0) {
1505 /* Enable derived sound device only if it does not match with
1506 one of the split sound devices. This is because the matching
1507 sound device was not disabled */
1508 bool should_enable = true;
1509 for (i = 0; i < num_devices; i++) {
1510 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1511 should_enable = false;
1512 break;
1513 }
1514 }
1515 if (should_enable)
1516 enable_snd_device(adev, derive_snd_device[usecase->id]);
1517 } else {
1518 enable_snd_device(adev, derive_snd_device[usecase->id]);
1519 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001520 }
1521 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001522
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001523 /* Re-route all the usecases on the shared backend other than the
1524 specified usecase to new snd devices */
1525 list_for_each(node, &adev->usecase_list) {
1526 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301527 /* Update the out_snd_device only before enabling the audio route */
1528 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301529 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301530 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301531 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301532 use_case_table[usecase->id],
1533 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001534 /* Update voc calibration before enabling VoIP route */
1535 if (usecase->type == VOIP_CALL)
1536 status = platform_switch_voice_call_device_post(adev->platform,
1537 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001538 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301539 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001540 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1541 out_set_voip_volume(&usecase->stream.out->stream,
1542 usecase->stream.out->volume_l,
1543 usecase->stream.out->volume_r);
1544 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301545 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001546 }
1547 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001548 }
1549}
1550
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301551static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001552 struct audio_usecase *uc_info,
1553 snd_device_t snd_device)
1554{
1555 struct listnode *node;
1556 struct audio_usecase *usecase;
1557 bool switch_device[AUDIO_USECASE_MAX];
1558 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301559 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001560 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001561
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301562 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1563 snd_device);
1564 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301565
1566 /*
1567 * Make sure out devices is checked against out codec backend device and
1568 * also in devices against in codec backend. Checking out device against in
1569 * codec backend or vice versa causes issues.
1570 */
1571 if (uc_info->type == PCM_CAPTURE)
1572 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001573 /*
1574 * This function is to make sure that all the active capture usecases
1575 * are always routed to the same input sound device.
1576 * For example, if audio-record and voice-call usecases are currently
1577 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1578 * is received for voice call then we have to make sure that audio-record
1579 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1580 * because of the limitation that two devices cannot be enabled
1581 * at the same time if they share the same backend.
1582 */
1583 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1584 switch_device[i] = false;
1585
1586 list_for_each(node, &adev->usecase_list) {
1587 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301588 /*
1589 * TODO: Enhance below condition to handle BT sco/USB multi recording
1590 */
Balázs Triszka6e101332018-02-26 22:11:10 +01001591
1592#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1593 if (usecase->id == USECASE_AUDIO_ULTRASOUND_TX)
1594 continue;
1595#endif
1596
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001597 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001598 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301599 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301600 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301601 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301602 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001603 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001604 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1605 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001606 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001607 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001608 switch_device[usecase->id] = true;
1609 num_uc_to_switch++;
1610 }
1611 }
1612
1613 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001614 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001615
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301616 /* Make sure the previous devices to be disabled first and then enable the
1617 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001618 list_for_each(node, &adev->usecase_list) {
1619 usecase = node_to_item(node, struct audio_usecase, list);
1620 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001621 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001622 }
1623 }
1624
1625 list_for_each(node, &adev->usecase_list) {
1626 usecase = node_to_item(node, struct audio_usecase, list);
1627 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001628 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001629 }
1630 }
1631
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001632 /* Re-route all the usecases on the shared backend other than the
1633 specified usecase to new snd devices */
1634 list_for_each(node, &adev->usecase_list) {
1635 usecase = node_to_item(node, struct audio_usecase, list);
1636 /* Update the in_snd_device only before enabling the audio route */
1637 if (switch_device[usecase->id] ) {
1638 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001639 if (usecase->type != VOICE_CALL) {
1640 /* Update voc calibration before enabling VoIP route */
1641 if (usecase->type == VOIP_CALL)
1642 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001643 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001644 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301645 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001646 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001647 }
1648 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001649 }
1650}
1651
Mingming Yin3a941d42016-02-17 18:08:05 -08001652static void reset_hdmi_sink_caps(struct stream_out *out) {
1653 int i = 0;
1654
1655 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1656 out->supported_channel_masks[i] = 0;
1657 }
1658 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1659 out->supported_formats[i] = 0;
1660 }
1661 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1662 out->supported_sample_rates[i] = 0;
1663 }
1664}
1665
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001666/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001667static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001668{
Mingming Yin3a941d42016-02-17 18:08:05 -08001669 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001670 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001671
Mingming Yin3a941d42016-02-17 18:08:05 -08001672 reset_hdmi_sink_caps(out);
1673
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001674 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001675 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001676 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001677 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001678 }
1679
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001680 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001681 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001682 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001683 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001684 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1685 case 6:
1686 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1687 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1688 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1689 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1690 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1691 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001692 break;
1693 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001694 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001695 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696 break;
1697 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001698
1699 // check channel format caps
1700 i = 0;
1701 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1702 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1703 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1704 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1705 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1706 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1707 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1708 }
1709
Ben Romberger1aaaf862017-04-06 17:49:46 -07001710 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1711 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1712 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1713 }
1714
Mingming Yin3a941d42016-02-17 18:08:05 -08001715 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1716 ALOGV(":%s HDMI supports DTS format", __func__);
1717 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1718 }
1719
1720 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1721 ALOGV(":%s HDMI supports DTS HD format", __func__);
1722 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1723 }
1724
Naresh Tanniru928f0862017-04-07 16:44:23 -07001725 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1726 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1727 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1728 }
1729
Mingming Yin3a941d42016-02-17 18:08:05 -08001730
1731 // check sample rate caps
1732 i = 0;
1733 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1734 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1735 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1736 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1737 }
1738 }
1739
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001740 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741}
1742
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001743static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1744 uint32_t *supported_sample_rates __unused,
1745 uint32_t max_rates __unused)
1746{
1747 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1748 supported_sample_rates,
1749 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301750 ssize_t i = 0;
1751
1752 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001753 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1754 supported_sample_rates[i]);
1755 }
1756 return count;
1757}
1758
1759static inline int read_usb_sup_channel_masks(bool is_playback,
1760 audio_channel_mask_t *supported_channel_masks,
1761 uint32_t max_masks)
1762{
1763 int channels = audio_extn_usb_get_max_channels(is_playback);
1764 int channel_count;
1765 uint32_t num_masks = 0;
1766 if (channels > MAX_HIFI_CHANNEL_COUNT)
1767 channels = MAX_HIFI_CHANNEL_COUNT;
1768
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301769 channel_count = DEFAULT_CHANNEL_COUNT;
1770
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001771 if (is_playback) {
1772 // For playback we never report mono because the framework always outputs stereo
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001773 // audio_channel_out_mask_from_count() does return positional masks for channel counts
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301774 // above 2 but we want indexed masks here.
1775 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001776 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001777 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1778 // indexed mask
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301779 supported_channel_masks[num_masks++] = audio_channel_in_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001780 }
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301781
1782 for (channel_count = channels; ((channel_count >= DEFAULT_CHANNEL_COUNT) &&
1783 (num_masks < max_masks)); channel_count--) {
1784 supported_channel_masks[num_masks++] =
1785 audio_channel_mask_for_index_assignment_from_count(channel_count);
1786 }
1787
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001788 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1789 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1790 return num_masks;
1791}
1792
1793static inline int read_usb_sup_formats(bool is_playback __unused,
1794 audio_format_t *supported_formats,
1795 uint32_t max_formats __unused)
1796{
1797 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1798 switch (bitwidth) {
1799 case 24:
1800 // XXX : usb.c returns 24 for s24 and s24_le?
1801 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1802 break;
1803 case 32:
1804 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1805 break;
1806 case 16:
1807 default :
1808 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1809 break;
1810 }
1811 ALOGV("%s: %s supported format %d", __func__,
1812 is_playback ? "P" : "C", bitwidth);
1813 return 1;
1814}
1815
1816static inline int read_usb_sup_params_and_compare(bool is_playback,
1817 audio_format_t *format,
1818 audio_format_t *supported_formats,
1819 uint32_t max_formats,
1820 audio_channel_mask_t *mask,
1821 audio_channel_mask_t *supported_channel_masks,
1822 uint32_t max_masks,
1823 uint32_t *rate,
1824 uint32_t *supported_sample_rates,
1825 uint32_t max_rates) {
1826 int ret = 0;
1827 int num_formats;
1828 int num_masks;
1829 int num_rates;
1830 int i;
1831
1832 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1833 max_formats);
1834 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1835 max_masks);
1836
1837 num_rates = read_usb_sup_sample_rates(is_playback,
1838 supported_sample_rates, max_rates);
1839
1840#define LUT(table, len, what, dflt) \
1841 for (i=0; i<len && (table[i] != what); i++); \
1842 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1843
1844 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1845 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1846 LUT(supported_sample_rates, num_rates, *rate, 0);
1847
1848#undef LUT
1849 return ret < 0 ? -EINVAL : 0; // HACK TBD
1850}
1851
Alexy Josephb1379942016-01-29 15:49:38 -08001852audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001853 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001854{
1855 struct audio_usecase *usecase;
1856 struct listnode *node;
1857
1858 list_for_each(node, &adev->usecase_list) {
1859 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001860 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001861 ALOGV("%s: usecase id %d", __func__, usecase->id);
1862 return usecase->id;
1863 }
1864 }
1865 return USECASE_INVALID;
1866}
1867
Alexy Josephb1379942016-01-29 15:49:38 -08001868struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001869 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001870{
1871 struct audio_usecase *usecase;
1872 struct listnode *node;
1873
1874 list_for_each(node, &adev->usecase_list) {
1875 usecase = node_to_item(node, struct audio_usecase, list);
1876 if (usecase->id == uc_id)
1877 return usecase;
1878 }
1879 return NULL;
1880}
1881
Dhananjay Kumard4833242016-10-06 22:09:12 +05301882struct stream_in *get_next_active_input(const struct audio_device *adev)
1883{
1884 struct audio_usecase *usecase;
1885 struct listnode *node;
1886
1887 list_for_each_reverse(node, &adev->usecase_list) {
1888 usecase = node_to_item(node, struct audio_usecase, list);
1889 if (usecase->type == PCM_CAPTURE)
1890 return usecase->stream.in;
1891 }
1892 return NULL;
1893}
1894
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301895/*
1896 * is a true native playback active
1897 */
1898bool audio_is_true_native_stream_active(struct audio_device *adev)
1899{
1900 bool active = false;
1901 int i = 0;
1902 struct listnode *node;
1903
1904 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1905 ALOGV("%s:napb: not in true mode or non hdphones device",
1906 __func__);
1907 active = false;
1908 goto exit;
1909 }
1910
1911 list_for_each(node, &adev->usecase_list) {
1912 struct audio_usecase *uc;
1913 uc = node_to_item(node, struct audio_usecase, list);
1914 struct stream_out *curr_out =
1915 (struct stream_out*) uc->stream.out;
1916
1917 if (curr_out && PCM_PLAYBACK == uc->type) {
1918 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1919 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1920 uc->id, curr_out->sample_rate,
1921 curr_out->bit_width,
1922 platform_get_snd_device_name(uc->out_snd_device));
1923
1924 if (is_offload_usecase(uc->id) &&
1925 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1926 active = true;
1927 ALOGD("%s:napb:native stream detected", __func__);
1928 }
1929 }
1930 }
1931exit:
1932 return active;
1933}
1934
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001935uint32_t adev_get_dsp_bit_width_enforce_mode()
1936{
1937 if (adev == NULL) {
1938 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1939 return 0;
1940 }
1941 return adev->dsp_bit_width_enforce_mode;
1942}
1943
1944static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1945{
1946 char value[PROPERTY_VALUE_MAX];
1947 int trial;
1948 uint32_t dsp_bit_width_enforce_mode = 0;
1949
1950 if (!mixer) {
1951 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1952 __func__);
1953 return 0;
1954 }
1955
1956 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1957 value, NULL) > 0) {
1958 trial = atoi(value);
1959 switch (trial) {
1960 case 16:
1961 dsp_bit_width_enforce_mode = 16;
1962 break;
1963 case 24:
1964 dsp_bit_width_enforce_mode = 24;
1965 break;
1966 case 32:
1967 dsp_bit_width_enforce_mode = 32;
1968 break;
1969 default:
1970 dsp_bit_width_enforce_mode = 0;
1971 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1972 break;
1973 }
1974 }
1975
1976 return dsp_bit_width_enforce_mode;
1977}
1978
1979static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1980 uint32_t enforce_mode,
1981 bool enable)
1982{
1983 struct mixer_ctl *ctl = NULL;
1984 const char *mixer_ctl_name = "ASM Bit Width";
1985 uint32_t asm_bit_width_mode = 0;
1986
1987 if (enforce_mode == 0) {
1988 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1989 return;
1990 }
1991
1992 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1993 if (!ctl) {
1994 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1995 __func__, mixer_ctl_name);
1996 return;
1997 }
1998
1999 if (enable)
2000 asm_bit_width_mode = enforce_mode;
2001 else
2002 asm_bit_width_mode = 0;
2003
2004 ALOGV("%s DSP bit width feature status is %d width=%d",
2005 __func__, enable, asm_bit_width_mode);
2006 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2007 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2008 asm_bit_width_mode);
2009
2010 return;
2011}
2012
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302013/*
2014 * if native DSD playback active
2015 */
2016bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2017{
2018 bool active = false;
2019 struct listnode *node = NULL;
2020 struct audio_usecase *uc = NULL;
2021 struct stream_out *curr_out = NULL;
2022
2023 list_for_each(node, &adev->usecase_list) {
2024 uc = node_to_item(node, struct audio_usecase, list);
2025 curr_out = (struct stream_out*) uc->stream.out;
2026
2027 if (curr_out && PCM_PLAYBACK == uc->type &&
2028 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2029 active = true;
2030 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302031 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302032 }
2033 }
2034 return active;
2035}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302036
2037static bool force_device_switch(struct audio_usecase *usecase)
2038{
2039 bool ret = false;
2040 bool is_it_true_mode = false;
2041
Zhou Song30f2c3e2018-02-08 14:02:15 +08002042 if (usecase->type == PCM_CAPTURE ||
2043 usecase->type == TRANSCODE_LOOPBACK) {
2044 return false;
2045 }
2046
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002047 if(usecase->stream.out == NULL) {
2048 ALOGE("%s: stream.out is NULL", __func__);
2049 return false;
2050 }
2051
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302052 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002053 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2054 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2055 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302056 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2057 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2058 (!is_it_true_mode && adev->native_playback_enabled)){
2059 ret = true;
2060 ALOGD("napb: time to toggle native mode");
2061 }
2062 }
2063
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302064 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302065 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2066 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002067 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302068 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302069 ALOGD("Force a2dp device switch to update new encoder config");
2070 ret = true;
2071 }
2072
Manish Dewangan671a4202017-08-18 17:30:46 +05302073 if (usecase->stream.out->stream_config_changed) {
2074 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2075 return true;
2076 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302077 return ret;
2078}
2079
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302080bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2081{
2082 bool ret=false;
2083 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2084 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2085 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2086 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2087 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2088 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2089 ret = true;
2090
2091 return ret;
2092}
2093
2094bool is_a2dp_device(snd_device_t out_snd_device)
2095{
2096 bool ret=false;
2097 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2098 ret = true;
2099
2100 return ret;
2101}
2102
2103bool is_bt_soc_on(struct audio_device *adev)
2104{
2105 struct mixer_ctl *ctl;
2106 char *mixer_ctl_name = "BT SOC status";
2107 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2108 bool bt_soc_status = true;
2109 if (!ctl) {
2110 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2111 __func__, mixer_ctl_name);
2112 /*This is to ensure we dont break targets which dont have the kernel change*/
2113 return true;
2114 }
2115 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2116 ALOGD("BT SOC status: %d",bt_soc_status);
2117 return bt_soc_status;
2118}
2119
2120int out_standby_l(struct audio_stream *stream);
2121
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002122int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002124 snd_device_t out_snd_device = SND_DEVICE_NONE;
2125 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002126 struct audio_usecase *usecase = NULL;
2127 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002128 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002129 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302130 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002131 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002132 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002133
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302134 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2135
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002136 usecase = get_usecase_from_list(adev, uc_id);
2137 if (usecase == NULL) {
2138 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2139 return -EINVAL;
2140 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002141
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002142 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002143 (usecase->type == VOIP_CALL) ||
2144 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302145 if(usecase->stream.out == NULL) {
2146 ALOGE("%s: stream.out is NULL", __func__);
2147 return -EINVAL;
2148 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002149 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002150 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002151 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002152 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302153 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
2154 if (usecase->stream.inout == NULL) {
2155 ALOGE("%s: stream.inout is NULL", __func__);
2156 return -EINVAL;
2157 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302158 stream_out.devices = usecase->stream.inout->out_config.devices;
2159 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2160 stream_out.format = usecase->stream.inout->out_config.format;
2161 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2162 out_snd_device = platform_get_output_snd_device(adev->platform,
2163 &stream_out);
2164 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302165 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002166 } else {
2167 /*
2168 * If the voice call is active, use the sound devices of voice call usecase
2169 * so that it would not result any device switch. All the usecases will
2170 * be switched to new device when select_devices() is called for voice call
2171 * usecase. This is to avoid switching devices for voice call when
2172 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002173 * choose voice call device only if the use case device is
2174 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002175 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002176 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002177 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002178 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002179 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2180 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302181 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2182 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002183 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002184 in_snd_device = vc_usecase->in_snd_device;
2185 out_snd_device = vc_usecase->out_snd_device;
2186 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002187 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002188 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002189 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002190 if ((voip_usecase != NULL) &&
2191 (usecase->type == PCM_PLAYBACK) &&
2192 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002193 out_snd_device_backend_match = platform_check_backends_match(
2194 voip_usecase->out_snd_device,
2195 platform_get_output_snd_device(
2196 adev->platform,
2197 usecase->stream.out));
2198 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002199 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002200 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2201 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002202 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002203 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002204 in_snd_device = voip_usecase->in_snd_device;
2205 out_snd_device = voip_usecase->out_snd_device;
2206 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002207 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002208 hfp_ucid = audio_extn_hfp_get_usecase();
2209 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002210 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002211 in_snd_device = hfp_usecase->in_snd_device;
2212 out_snd_device = hfp_usecase->out_snd_device;
2213 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002214 }
2215 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302216 if (usecase->stream.out == NULL) {
2217 ALOGE("%s: stream.out is NULL", __func__);
2218 return -EINVAL;
2219 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002220 usecase->devices = usecase->stream.out->devices;
2221 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002222 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002223 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002224 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002225 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleiz3ca773f2018-10-12 15:49:35 +08002226 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002227 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2228
2229 if ((usecase->stream.out != NULL &&
2230 voip_usecase != NULL &&
2231 usecase->stream.out->usecase == voip_usecase->id) &&
2232 adev->active_input &&
kunleiz3ca773f2018-10-12 15:49:35 +08002233 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002234 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002235 select_devices(adev, adev->active_input->usecase);
2236 }
2237 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002238 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302239 if (usecase->stream.in == NULL) {
2240 ALOGE("%s: stream.in is NULL", __func__);
2241 return -EINVAL;
2242 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002243 usecase->devices = usecase->stream.in->device;
2244 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002245 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002246 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002247 if (adev->active_input &&
2248 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302249 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002250 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2251 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2252 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2253 out_device = voip_usecase->stream.out->devices;
2254 else if (adev->primary_output && !adev->primary_output->standby)
2255 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002256 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002257 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2258 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002259 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002260 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002261 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002262 }
2263 }
2264
2265 if (out_snd_device == usecase->out_snd_device &&
2266 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302267
2268 if (!force_device_switch(usecase))
2269 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270 }
2271
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302272 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
2273 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
2274 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2275 return 0;
2276 }
2277
sangwoobc677242013-08-08 16:53:43 +09002278 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07002279 out_snd_device, platform_get_snd_device_name(out_snd_device),
2280 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002281
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002282 /*
2283 * Limitation: While in call, to do a device switch we need to disable
2284 * and enable both RX and TX devices though one of them is same as current
2285 * device.
2286 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002287 if ((usecase->type == VOICE_CALL) &&
2288 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2289 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002290 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002291 }
2292
2293 if (((usecase->type == VOICE_CALL) ||
2294 (usecase->type == VOIP_CALL)) &&
2295 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2296 /* Disable sidetone only if voice/voip call already exists */
2297 if (voice_is_call_state_active(adev) ||
2298 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002299 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002300
2301 /* Disable aanc only if voice call exists */
2302 if (voice_is_call_state_active(adev))
2303 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002304 }
2305
Zhou Songc66eb7e2017-08-08 18:29:07 +08002306 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302307 (!audio_extn_a2dp_is_ready())) {
2308 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002309 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302310 }
2311
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002312 /* Disable current sound devices */
2313 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002314 disable_audio_route(adev, usecase);
2315 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002316 }
2317
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002318 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002319 disable_audio_route(adev, usecase);
2320 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002321 }
2322
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002323 /* Applicable only on the targets that has external modem.
2324 * New device information should be sent to modem before enabling
2325 * the devices to reduce in-call device switch time.
2326 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002327 if ((usecase->type == VOICE_CALL) &&
2328 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2329 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002330 status = platform_switch_voice_call_enable_device_config(adev->platform,
2331 out_snd_device,
2332 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002333 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002334
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002335 /* Enable new sound devices */
2336 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002337 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302338 if (platform_check_codec_asrc_support(adev->platform))
2339 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002340 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341 }
2342
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002343 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302344 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002345 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002346 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002347
Avinash Vaish71a8b972014-07-24 15:36:33 +05302348 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002349 status = platform_switch_voice_call_device_post(adev->platform,
2350 out_snd_device,
2351 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302352 enable_audio_route_for_voice_usecases(adev, usecase);
2353 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002354
sangwoo170731f2013-06-08 15:36:36 +09002355 usecase->in_snd_device = in_snd_device;
2356 usecase->out_snd_device = out_snd_device;
2357
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302358 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2359 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302360 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002361 if ((24 == usecase->stream.out->bit_width) &&
2362 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2363 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2364 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2365 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2366 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2367 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2368 /*
2369 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2370 * configured device sample rate, if not update the COPP rate to be equal to the
2371 * device sample rate, else open COPP at stream sample rate
2372 */
2373 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2374 usecase->stream.out->sample_rate,
2375 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302376 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2377 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002378 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2379 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2380 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2381 }
Weiyin Jiang619761e2019-07-08 16:13:16 +08002382 }
2383 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002384
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002385 /* If input stream is already running then effect needs to be
2386 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002387 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2388 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002389 check_and_enable_effect(adev);
2390
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002391 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002392 /* Enable aanc only if voice call exists */
2393 if (voice_is_call_state_active(adev))
2394 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2395
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002396 /* Enable sidetone only if other voice/voip call already exists */
2397 if (voice_is_call_state_active(adev) ||
2398 voice_extn_compress_voip_is_started(adev))
2399 voice_set_sidetone(adev, out_snd_device, true);
2400 }
2401
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05302402 /* Rely on amplifier_set_devices to distinguish between in/out devices */
2403 amplifier_set_input_devices(in_snd_device);
2404 amplifier_set_output_devices(out_snd_device);
2405
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002406 /* Applicable only on the targets that has external modem.
2407 * Enable device command should be sent to modem only after
2408 * enabling voice call mixer controls
2409 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002410 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002411 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2412 out_snd_device,
2413 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302414
2415 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2416
2417 if (usecase->type == VOIP_CALL) {
2418 if (adev->active_input != NULL &&
2419 !adev->active_input->standby) {
2420 if (is_bt_soc_on(adev) == false){
2421 ALOGD("BT SCO MIC disconnected while in connection");
2422 if (adev->active_input->pcm != NULL)
2423 pcm_stop(adev->active_input->pcm);
2424 }
2425 }
2426 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2427 && usecase->stream.out->started) {
2428 if (is_bt_soc_on(adev) == false) {
2429 ALOGD("BT SCO/A2DP disconnected while in connection");
2430 out_standby_l(&usecase->stream.out->stream.common);
2431 }
2432 }
2433 } else if ((usecase->stream.out != NULL) &&
2434 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2435 usecase->stream.out->started) {
2436 if (is_bt_soc_on(adev) == false) {
2437 ALOGD("BT SCO/A2dp disconnected while in connection");
2438 out_standby_l(&usecase->stream.out->stream.common);
2439 }
2440 }
2441 }
2442
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302443 ALOGD("%s: done",__func__);
2444
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002445 return status;
2446}
2447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002448static int stop_input_stream(struct stream_in *in)
2449{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302450 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302452
2453 if (in == NULL) {
2454 ALOGE("%s: stream_in ptr is NULL", __func__);
2455 return -EINVAL;
2456 }
2457
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002458 struct audio_device *adev = in->dev;
2459
Eric Laurent994a6932013-07-17 11:51:42 -07002460 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002461 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462 uc_info = get_usecase_from_list(adev, in->usecase);
2463 if (uc_info == NULL) {
2464 ALOGE("%s: Could not find the usecase (%d) in the list",
2465 __func__, in->usecase);
2466 return -EINVAL;
2467 }
2468
Derek Chencdd17c72014-11-24 12:39:14 -08002469 if (uc_info->in_snd_device != SND_DEVICE_NONE) {
2470 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2471 ALOGE("%s: failed to stop ext hw plugin", __func__);
2472 }
2473
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002474 /* Close in-call recording streams */
2475 voice_check_and_stop_incall_rec_usecase(adev, in);
2476
Eric Laurent150dbfe2013-02-27 14:31:02 -08002477 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002478 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002479
2480 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002481 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002483 list_remove(&uc_info->list);
2484 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002486 adev->active_input = get_next_active_input(adev);
Vatsal Buchaa1358992018-11-14 13:25:08 +05302487 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002488 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489 return ret;
2490}
2491
2492int start_input_stream(struct stream_in *in)
2493{
2494 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002495 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302497
2498 if (in == NULL) {
2499 ALOGE("%s: stream_in ptr is NULL", __func__);
2500 return -EINVAL;
2501 }
2502
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002504 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002505 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506
Mingming Yin2664a5b2015-09-03 10:53:11 -07002507 if (get_usecase_from_list(adev, usecase) == NULL)
2508 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302509 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2510 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002511
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302512 if (CARD_STATUS_OFFLINE == in->card_status||
2513 CARD_STATUS_OFFLINE == adev->card_status) {
2514 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302515 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302516 goto error_config;
2517 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302518
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302519 if (audio_is_bluetooth_sco_device(in->device)) {
2520 if (!adev->bt_sco_on) {
2521 ALOGE("%s: SCO profile is not ready, return error", __func__);
2522 ret = -EIO;
2523 goto error_config;
2524 }
2525 }
2526
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002527 /* Check if source matches incall recording usecase criteria */
2528 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2529 if (ret)
2530 goto error_config;
2531 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002532 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2533
2534 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2535 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2536 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002537 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002538 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002539
Eric Laurentb23d5282013-05-14 15:27:20 -07002540 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541 if (in->pcm_device_id < 0) {
2542 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2543 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002544 ret = -EINVAL;
2545 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002547
2548 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002550
2551 if (!uc_info) {
2552 ret = -ENOMEM;
2553 goto error_config;
2554 }
2555
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556 uc_info->id = in->usecase;
2557 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002558 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002559 uc_info->devices = in->device;
2560 uc_info->in_snd_device = SND_DEVICE_NONE;
2561 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002562
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002563 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302564 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2565 adev->perf_lock_opts,
2566 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002567 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568
Derek Chencdd17c72014-11-24 12:39:14 -08002569 if (uc_info->in_snd_device != SND_DEVICE_NONE) {
2570 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2571 ALOGE("%s: failed to start ext hw plugin", __func__);
2572 }
2573
Haynes Mathew George16081042017-05-31 17:16:49 -07002574 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302575 ret = audio_extn_cin_start_input_stream(in);
2576 if (ret)
2577 goto error_open;
2578 else
2579 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002580 }
2581
Haynes Mathew George16081042017-05-31 17:16:49 -07002582 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002583 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002584 ALOGE("%s: pcm stream not ready", __func__);
2585 goto error_open;
2586 }
2587 ret = pcm_start(in->pcm);
2588 if (ret < 0) {
2589 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2590 goto error_open;
2591 }
2592 } else {
2593 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2594 unsigned int pcm_open_retry_count = 0;
2595
2596 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2597 flags |= PCM_MMAP | PCM_NOIRQ;
2598 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2599 } else if (in->realtime) {
2600 flags |= PCM_MMAP | PCM_NOIRQ;
2601 }
2602
Garmond Leunge2433c32017-09-28 21:51:22 -07002603 if (audio_extn_ffv_get_stream() == in) {
2604 ALOGD("%s: ffv stream, update pcm config", __func__);
2605 audio_extn_ffv_update_pcm_config(&config);
2606 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002607 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2608 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2609
2610 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002611 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002612 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002613 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002614 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05302615 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
2616 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2617 adev->card_status = CARD_STATUS_OFFLINE;
2618 in->card_status = CARD_STATUS_OFFLINE;
2619 ret = -EIO;
2620 goto error_open;
2621 }
2622
Haynes Mathew George16081042017-05-31 17:16:49 -07002623 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2624 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2625 if (in->pcm != NULL) {
2626 pcm_close(in->pcm);
2627 in->pcm = NULL;
2628 }
2629 if (pcm_open_retry_count-- == 0) {
2630 ret = -EIO;
2631 goto error_open;
2632 }
2633 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2634 continue;
2635 }
2636 break;
2637 }
2638
2639 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002640 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002641 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002642 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002643 if (ret < 0) {
2644 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2645 pcm_close(in->pcm);
2646 in->pcm = NULL;
2647 goto error_open;
2648 }
2649 register_in_stream(in);
2650 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002651 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002652 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002653 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002654 if (ret < 0) {
2655 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002656 pcm_close(in->pcm);
2657 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002658 goto error_open;
2659 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002660 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002661 }
2662
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002663 check_and_enable_effect(adev);
2664
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302665done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302666 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002667 ALOGD("%s: exit", __func__);
Vatsal Buchaa1358992018-11-14 13:25:08 +05302668 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002669 return ret;
2670
2671error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302672 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002674error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302675 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302676 /*
2677 * sleep 50ms to allow sufficient time for kernel
2678 * drivers to recover incases like SSR.
2679 */
2680 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002681 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchaa1358992018-11-14 13:25:08 +05302682 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002683 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684}
2685
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002686void lock_input_stream(struct stream_in *in)
2687{
2688 pthread_mutex_lock(&in->pre_lock);
2689 pthread_mutex_lock(&in->lock);
2690 pthread_mutex_unlock(&in->pre_lock);
2691}
2692
2693void lock_output_stream(struct stream_out *out)
2694{
2695 pthread_mutex_lock(&out->pre_lock);
2696 pthread_mutex_lock(&out->lock);
2697 pthread_mutex_unlock(&out->pre_lock);
2698}
2699
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002700/* must be called with out->lock locked */
2701static int send_offload_cmd_l(struct stream_out* out, int command)
2702{
2703 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2704
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002705 if (!cmd) {
2706 ALOGE("failed to allocate mem for command 0x%x", command);
2707 return -ENOMEM;
2708 }
2709
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002710 ALOGVV("%s %d", __func__, command);
2711
2712 cmd->cmd = command;
2713 list_add_tail(&out->offload_cmd_list, &cmd->node);
2714 pthread_cond_signal(&out->offload_cond);
2715 return 0;
2716}
2717
2718/* must be called iwth out->lock locked */
2719static void stop_compressed_output_l(struct stream_out *out)
2720{
2721 out->offload_state = OFFLOAD_STATE_IDLE;
2722 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002723 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002724 if (out->compr != NULL) {
2725 compress_stop(out->compr);
2726 while (out->offload_thread_blocked) {
2727 pthread_cond_wait(&out->cond, &out->lock);
2728 }
2729 }
2730}
2731
Varun Balaraje49253e2017-07-06 19:48:56 +05302732bool is_interactive_usecase(audio_usecase_t uc_id)
2733{
2734 unsigned int i;
2735 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2736 if (uc_id == interactive_usecases[i])
2737 return true;
2738 }
2739 return false;
2740}
2741
2742static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2743{
2744 audio_usecase_t ret_uc = USECASE_INVALID;
2745 unsigned int intract_uc_index;
2746 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2747
2748 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2749 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2750 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2751 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2752 ret_uc = interactive_usecases[intract_uc_index];
2753 break;
2754 }
2755 }
2756
2757 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2758 return ret_uc;
2759}
2760
2761static void free_interactive_usecase(struct audio_device *adev,
2762 audio_usecase_t uc_id)
2763{
2764 unsigned int interact_uc_index;
2765 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2766
2767 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2768 if (interactive_usecases[interact_uc_index] == uc_id) {
2769 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2770 break;
2771 }
2772 }
2773 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2774}
2775
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002776bool is_offload_usecase(audio_usecase_t uc_id)
2777{
2778 unsigned int i;
2779 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2780 if (uc_id == offload_usecases[i])
2781 return true;
2782 }
2783 return false;
2784}
2785
Dhananjay Kumarac341582017-02-23 23:42:25 +05302786static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002787{
vivek mehta446c3962015-09-14 10:57:35 -07002788 audio_usecase_t ret_uc = USECASE_INVALID;
2789 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002790 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002791 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302792 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002793 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2794 else
2795 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002796
vivek mehta446c3962015-09-14 10:57:35 -07002797 pthread_mutex_lock(&adev->lock);
2798 if (get_usecase_from_list(adev, ret_uc) != NULL)
2799 ret_uc = USECASE_INVALID;
2800 pthread_mutex_unlock(&adev->lock);
2801
2802 return ret_uc;
2803 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002804
2805 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002806 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2807 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2808 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2809 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002810 break;
2811 }
2812 }
vivek mehta446c3962015-09-14 10:57:35 -07002813
2814 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2815 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002816}
2817
2818static void free_offload_usecase(struct audio_device *adev,
2819 audio_usecase_t uc_id)
2820{
vivek mehta446c3962015-09-14 10:57:35 -07002821 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002822 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002823
2824 if (!adev->multi_offload_enable)
2825 return;
2826
2827 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2828 if (offload_usecases[offload_uc_index] == uc_id) {
2829 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002830 break;
2831 }
2832 }
2833 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2834}
2835
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002836static void *offload_thread_loop(void *context)
2837{
2838 struct stream_out *out = (struct stream_out *) context;
2839 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002840 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002841
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002842 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2843 set_sched_policy(0, SP_FOREGROUND);
2844 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2845
2846 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002847 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002848 for (;;) {
2849 struct offload_cmd *cmd = NULL;
2850 stream_callback_event_t event;
2851 bool send_callback = false;
2852
2853 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2854 __func__, list_empty(&out->offload_cmd_list),
2855 out->offload_state);
2856 if (list_empty(&out->offload_cmd_list)) {
2857 ALOGV("%s SLEEPING", __func__);
2858 pthread_cond_wait(&out->offload_cond, &out->lock);
2859 ALOGV("%s RUNNING", __func__);
2860 continue;
2861 }
2862
2863 item = list_head(&out->offload_cmd_list);
2864 cmd = node_to_item(item, struct offload_cmd, node);
2865 list_remove(item);
2866
2867 ALOGVV("%s STATE %d CMD %d out->compr %p",
2868 __func__, out->offload_state, cmd->cmd, out->compr);
2869
2870 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2871 free(cmd);
2872 break;
2873 }
2874
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002875 // allow OFFLOAD_CMD_ERROR reporting during standby
2876 // this is needed to handle failures during compress_open
2877 // Note however that on a pause timeout, the stream is closed
2878 // and no offload usecase will be active. Therefore this
2879 // special case is needed for compress_open failures alone
2880 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2881 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002882 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002883 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002884 pthread_cond_signal(&out->cond);
2885 continue;
2886 }
2887 out->offload_thread_blocked = true;
2888 pthread_mutex_unlock(&out->lock);
2889 send_callback = false;
2890 switch(cmd->cmd) {
2891 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002892 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002893 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002894 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895 send_callback = true;
2896 event = STREAM_CBK_EVENT_WRITE_READY;
2897 break;
2898 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002899 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302900 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002901 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302902 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002903 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302904 if (ret < 0)
2905 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302906 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302907 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002908 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002909 else
2910 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002911 if (-ENETRESET != ret && !(-EINTR == ret &&
2912 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302913 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302914 pthread_mutex_lock(&out->lock);
2915 out->send_new_metadata = 1;
2916 out->send_next_track_params = true;
2917 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302918 event = STREAM_CBK_EVENT_DRAIN_READY;
2919 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2920 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302921 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002922 break;
2923 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002924 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002925 ret = compress_drain(out->compr);
2926 ALOGD("copl(%p):out of compress_drain", out);
2927 // EINTR check avoids drain interruption due to SSR
2928 if (-ENETRESET != ret && !(-EINTR == ret &&
2929 CARD_STATUS_OFFLINE == out->card_status)) {
2930 send_callback = true;
2931 event = STREAM_CBK_EVENT_DRAIN_READY;
2932 } else
2933 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002934 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302935 case OFFLOAD_CMD_ERROR:
2936 ALOGD("copl(%p): sending error callback to AF", out);
2937 send_callback = true;
2938 event = STREAM_CBK_EVENT_ERROR;
2939 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002940 default:
2941 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2942 break;
2943 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002944 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002945 out->offload_thread_blocked = false;
2946 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002947 if (send_callback && out->client_callback) {
2948 ALOGVV("%s: sending client_callback event %d", __func__, event);
2949 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002950 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002951 free(cmd);
2952 }
2953
2954 pthread_cond_signal(&out->cond);
2955 while (!list_empty(&out->offload_cmd_list)) {
2956 item = list_head(&out->offload_cmd_list);
2957 list_remove(item);
2958 free(node_to_item(item, struct offload_cmd, node));
2959 }
2960 pthread_mutex_unlock(&out->lock);
2961
2962 return NULL;
2963}
2964
2965static int create_offload_callback_thread(struct stream_out *out)
2966{
2967 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2968 list_init(&out->offload_cmd_list);
2969 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2970 offload_thread_loop, out);
2971 return 0;
2972}
2973
2974static int destroy_offload_callback_thread(struct stream_out *out)
2975{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002976 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002977 stop_compressed_output_l(out);
2978 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2979
2980 pthread_mutex_unlock(&out->lock);
2981 pthread_join(out->offload_thread, (void **) NULL);
2982 pthread_cond_destroy(&out->offload_cond);
2983
2984 return 0;
2985}
2986
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987static int stop_output_stream(struct stream_out *out)
2988{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302989 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990 struct audio_usecase *uc_info;
2991 struct audio_device *adev = out->dev;
2992
Eric Laurent994a6932013-07-17 11:51:42 -07002993 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002994 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 uc_info = get_usecase_from_list(adev, out->usecase);
2996 if (uc_info == NULL) {
2997 ALOGE("%s: Could not find the usecase (%d) in the list",
2998 __func__, out->usecase);
2999 return -EINVAL;
3000 }
3001
Derek Chencdd17c72014-11-24 12:39:14 -08003002 if (uc_info->out_snd_device != SND_DEVICE_NONE) {
3003 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3004 ALOGE("%s: failed to stop ext hw plugin", __func__);
3005 }
3006
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003007 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303008 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003009 if (adev->visualizer_stop_output != NULL)
3010 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003011
3012 audio_extn_dts_remove_state_notifier_node(out->usecase);
3013
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003014 if (adev->offload_effects_stop_output != NULL)
3015 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
3016 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003017
Arun Mirpuridbef0c72018-09-12 18:36:10 -07003018 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3019 out->usecase == USECASE_INCALL_MUSIC_UPLINK2)
Arun Mirpurief53ce52018-09-11 18:00:09 -07003020 voice_set_device_mute_flag(adev, false);
3021
Eric Laurent150dbfe2013-02-27 14:31:02 -08003022 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003023 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003024
3025 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003026 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003028 if (is_offload_usecase(out->usecase)) {
3029 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3030 adev->dsp_bit_width_enforce_mode,
3031 false);
3032 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003033 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3034 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3035 false);
3036
3037 if (ret != 0)
3038 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3039 /* default service interval was successfully updated,
3040 reopen USB backend with new service interval */
3041 ret = 0;
3042 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003043
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003044 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303045 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003046 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303047 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003048 ALOGV("Disable passthrough , reset mixer to pcm");
3049 /* NO_PASSTHROUGH */
3050 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003051 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003052 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3053 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003054
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303055 /* Must be called after removing the usecase from list */
3056 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303057 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303058
Manish Dewangan21a850a2017-08-14 12:03:55 +05303059 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003060 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3061 if (ret < 0)
3062 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3063 }
3064
Garmond Leung5fd0b552018-04-17 11:56:12 -07003065 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003066 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067 return ret;
3068}
3069
3070int start_output_stream(struct stream_out *out)
3071{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003072 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 struct audio_usecase *uc_info;
3074 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003075 char mixer_ctl_name[128];
3076 struct mixer_ctl *ctl = NULL;
3077 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303078 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079
Haynes Mathew George380745d2017-10-04 15:27:45 -07003080 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003081 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3082 ret = -EINVAL;
3083 goto error_config;
3084 }
3085
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303086 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
3087 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
3088 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303089
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303090 if (CARD_STATUS_OFFLINE == out->card_status ||
3091 CARD_STATUS_OFFLINE == adev->card_status) {
3092 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303093 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303094 goto error_config;
3095 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303096
Arun Mirpuridbef0c72018-09-12 18:36:10 -07003097 //Update incall music usecase to reflect correct voice session
3098 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3099 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3100 if (ret != 0) {
3101 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3102 __func__, ret);
3103 goto error_config;
3104 }
3105 }
3106
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303107 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
3108 if (!audio_extn_a2dp_is_ready()) {
3109 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303110 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303111 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303112 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3113 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3114 ret = -EAGAIN;
3115 goto error_config;
3116 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303117 }
3118 }
3119 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303120 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3121 if (!adev->bt_sco_on) {
3122 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3123 //combo usecase just by pass a2dp
3124 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3125 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3126 } else {
3127 ALOGE("%s: SCO profile is not ready, return error", __func__);
3128 ret = -EAGAIN;
3129 goto error_config;
3130 }
3131 }
3132 }
3133
Eric Laurentb23d5282013-05-14 15:27:20 -07003134 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135 if (out->pcm_device_id < 0) {
3136 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3137 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003138 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003139 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140 }
3141
3142 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003143
3144 if (!uc_info) {
3145 ret = -ENOMEM;
3146 goto error_config;
3147 }
3148
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149 uc_info->id = out->usecase;
3150 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003151 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003152 uc_info->devices = out->devices;
3153 uc_info->in_snd_device = SND_DEVICE_NONE;
3154 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003155
3156 /* This must be called before adding this usecase to the list */
3157 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3158 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3159 /* USB backend is not reopened immediately.
3160 This is eventually done as part of select_devices */
3161 }
3162
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003163 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003164
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303165 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3166 adev->perf_lock_opts,
3167 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303168
3169 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303170 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303171 if (audio_extn_passthru_is_enabled() &&
3172 audio_extn_passthru_is_passthrough_stream(out)) {
3173 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303174 }
3175 }
3176
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303177 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3178 (!audio_extn_a2dp_is_ready())) {
3179 if (!a2dp_combo) {
3180 check_a2dp_restore_l(adev, out, false);
3181 } else {
3182 audio_devices_t dev = out->devices;
3183 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3184 select_devices(adev, out->usecase);
3185 out->devices = dev;
3186 }
3187 } else {
3188 select_devices(adev, out->usecase);
3189 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003190
Arun Mirpuridbef0c72018-09-12 18:36:10 -07003191 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3192 out->usecase == USECASE_INCALL_MUSIC_UPLINK2)
Arun Mirpurief53ce52018-09-11 18:00:09 -07003193 voice_set_device_mute_flag(adev, true);
3194
Derek Chencdd17c72014-11-24 12:39:14 -08003195 if (uc_info->out_snd_device != SND_DEVICE_NONE) {
3196 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3197 ALOGE("%s: failed to start ext hw plugin", __func__);
3198 }
3199
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003200 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3201 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003202
3203 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuriebe78a72018-10-04 18:23:46 -07003204 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003205 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3206 ALOGE("%s: pcm stream not ready", __func__);
3207 goto error_open;
3208 }
3209 ret = pcm_start(out->pcm);
3210 if (ret < 0) {
3211 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3212 goto error_open;
3213 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07003214 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003215 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003216 unsigned int flags = PCM_OUT;
3217 unsigned int pcm_open_retry_count = 0;
3218 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3219 flags |= PCM_MMAP | PCM_NOIRQ;
3220 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003221 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003222 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003223 } else
3224 flags |= PCM_MONOTONIC;
3225
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003226 if ((adev->vr_audio_mode_enabled) &&
3227 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3228 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3229 "PCM_Dev %d Topology", out->pcm_device_id);
3230 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3231 if (!ctl) {
3232 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3233 __func__, mixer_ctl_name);
3234 } else {
3235 //if success use ULLPP
3236 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3237 __func__, mixer_ctl_name, out->pcm_device_id);
3238 //There is a still a possibility that some sessions
3239 // that request for FAST|RAW when 3D audio is active
3240 //can go through ULLPP. Ideally we expects apps to
3241 //listen to audio focus and stop concurrent playback
3242 //Also, we will look for mode flag (voice_in_communication)
3243 //before enabling the realtime flag.
3244 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3245 }
3246 }
3247
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003248 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003249 ATRACE_BEGIN("pcm_open");
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003250 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3251 flags, &out->config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003252 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05303253 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
3254 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3255 out->card_status = CARD_STATUS_OFFLINE;
3256 adev->card_status = CARD_STATUS_OFFLINE;
3257 ret = -EIO;
3258 goto error_open;
3259 }
3260
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003261 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3262 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3263 if (out->pcm != NULL) {
3264 pcm_close(out->pcm);
3265 out->pcm = NULL;
3266 }
3267 if (pcm_open_retry_count-- == 0) {
3268 ret = -EIO;
3269 goto error_open;
3270 }
3271 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3272 continue;
3273 }
3274 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003275 }
Surendar Karka5a18a7a2018-04-26 11:28:38 +05303276 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3277 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003278
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003279 ALOGV("%s: pcm_prepare", __func__);
3280 if (pcm_is_ready(out->pcm)) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003281 ATRACE_BEGIN("pcm_prepare");
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003282 ret = pcm_prepare(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003283 ATRACE_END();
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003284 if (ret < 0) {
3285 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3286 pcm_close(out->pcm);
3287 out->pcm = NULL;
3288 goto error_open;
3289 }
3290 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08003291 // apply volume for voip playback after path is set up
3292 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3293 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003294 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003295 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303296 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003297 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3298 adev->dsp_bit_width_enforce_mode,
3299 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003301 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003302 out->compr = compress_open(adev->snd_card,
3303 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003304 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003305 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05303306 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
3307 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3308 adev->card_status = CARD_STATUS_OFFLINE;
3309 out->card_status = CARD_STATUS_OFFLINE;
3310 ret = -EIO;
3311 goto error_open;
3312 }
3313
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003314 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003315 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003316 compress_close(out->compr);
3317 out->compr = NULL;
3318 ret = -EIO;
3319 goto error_open;
3320 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303321 /* compress_open sends params of the track, so reset the flag here */
3322 out->is_compr_metadata_avail = false;
3323
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003324 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003325 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003326
Fred Oh3f43e742015-03-04 18:42:34 -08003327 /* Since small bufs uses blocking writes, a write will be blocked
3328 for the default max poll time (20s) in the event of an SSR.
3329 Reduce the poll time to observe and deal with SSR faster.
3330 */
Ashish Jain5106d362016-05-11 19:23:33 +05303331 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003332 compress_set_max_poll_wait(out->compr, 1000);
3333 }
3334
Manish Dewangan69426c82017-01-30 17:35:36 +05303335 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303336 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303337
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003338 audio_extn_dts_create_state_notifier_node(out->usecase);
3339 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3340 popcount(out->channel_mask),
3341 out->playback_started);
3342
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003343#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303344 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003345 audio_extn_dolby_send_ddp_endp_params(adev);
3346#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303347 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3348 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003349 if (adev->visualizer_start_output != NULL)
3350 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3351 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303352 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003353 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003354 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003356
3357 if (ret == 0) {
3358 register_out_stream(out);
3359 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003360 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3361 ALOGE("%s: pcm stream not ready", __func__);
3362 goto error_open;
3363 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003364 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003365 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003366 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003367 if (ret < 0)
3368 goto error_open;
3369 }
3370 }
3371
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303372 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003373 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003374
Manish Dewangan21a850a2017-08-14 12:03:55 +05303375 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003376 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003377 if (ret < 0)
3378 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3379 }
3380
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003381 // consider a scenario where on pause lower layers are tear down.
3382 // so on resume, swap mixer control need to be sent only when
3383 // backend is active, hence rather than sending from enable device
3384 // sending it from start of streamtream
3385
3386 platform_set_swap_channels(adev, true);
3387
Haynes Mathew George380745d2017-10-04 15:27:45 -07003388 ATRACE_END();
Vatsal Buchaa1358992018-11-14 13:25:08 +05303389 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003390 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003391error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303392 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003394error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303395 /*
3396 * sleep 50ms to allow sufficient time for kernel
3397 * drivers to recover incases like SSR.
3398 */
3399 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003400 ATRACE_END();
Vatsal Buchaa1358992018-11-14 13:25:08 +05303401 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003402 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403}
3404
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405static int check_input_parameters(uint32_t sample_rate,
3406 audio_format_t format,
3407 int channel_count)
3408{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003409 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003410
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303411 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3412 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3413 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003414 !voice_extn_compress_voip_is_format_supported(format) &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003415 !audio_extn_compr_cap_format_supported(format))
3416 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003417
3418 switch (channel_count) {
3419 case 1:
3420 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303421 case 3:
3422 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003423 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003424 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003425 break;
3426 default:
3427 ret = -EINVAL;
3428 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429
3430 switch (sample_rate) {
3431 case 8000:
3432 case 11025:
3433 case 12000:
3434 case 16000:
3435 case 22050:
3436 case 24000:
3437 case 32000:
3438 case 44100:
3439 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003440 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303441 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003442 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303443 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003444 break;
3445 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003446 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447 }
3448
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003449 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450}
3451
Naresh Tanniru04f71882018-06-26 17:46:22 +05303452
3453/** Add a value in a list if not already present.
3454 * @return true if value was successfully inserted or already present,
3455 * false if the list is full and does not contain the value.
3456 */
3457static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3458 for (size_t i = 0; i < list_length; i++) {
3459 if (list[i] == value) return true; // value is already present
3460 if (list[i] == 0) { // no values in this slot
3461 list[i] = value;
3462 return true; // value inserted
3463 }
3464 }
3465 return false; // could not insert value
3466}
3467
3468/** Add channel_mask in supported_channel_masks if not already present.
3469 * @return true if channel_mask was successfully inserted or already present,
3470 * false if supported_channel_masks is full and does not contain channel_mask.
3471 */
3472static void register_channel_mask(audio_channel_mask_t channel_mask,
3473 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3474 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3475 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3476}
3477
3478/** Add format in supported_formats if not already present.
3479 * @return true if format was successfully inserted or already present,
3480 * false if supported_formats is full and does not contain format.
3481 */
3482static void register_format(audio_format_t format,
3483 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3484 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3485 "%s: stream can not declare supporting its format %x", __func__, format);
3486}
3487/** Add sample_rate in supported_sample_rates if not already present.
3488 * @return true if sample_rate was successfully inserted or already present,
3489 * false if supported_sample_rates is full and does not contain sample_rate.
3490 */
3491static void register_sample_rate(uint32_t sample_rate,
3492 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3493 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3494 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3495}
3496
Karthikeyan Mani35531922018-11-07 15:44:13 -08003497static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3498{
3499 uint32_t high = num1, low = num2, temp = 0;
3500
3501 if (!num1 || !num2)
3502 return 0;
3503
3504 if (num1 < num2) {
3505 high = num2;
3506 low = num1;
3507 }
3508
3509 while (low != 0) {
3510 temp = low;
3511 low = high % low;
3512 high = temp;
3513 }
3514 return (num1 * num2)/high;
3515}
3516
3517static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3518{
3519 uint32_t remainder = 0;
3520
3521 if (!multiplier)
3522 return num;
3523
3524 remainder = num % multiplier;
3525 if (remainder)
3526 num += (multiplier - remainder);
3527
3528 return num;
3529}
3530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531static size_t get_input_buffer_size(uint32_t sample_rate,
3532 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003533 int channel_count,
3534 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535{
3536 size_t size = 0;
Karthikeyan Mani35531922018-11-07 15:44:13 -08003537 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003539 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3540 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003541
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003542 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003543 if (is_low_latency)
3544 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303545
Karthikeyan Mani35531922018-11-07 15:44:13 -08003546 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
3547 size *= bytes_per_period_sample;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003548
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003549 /* make sure the size is multiple of 32 bytes
3550 * At 48 kHz mono 16-bit PCM:
3551 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3552 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Mani35531922018-11-07 15:44:13 -08003553 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003554 */
Karthikeyan Mani35531922018-11-07 15:44:13 -08003555 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003556
3557 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003558}
3559
Ashish Jain058165c2016-09-28 23:18:48 +05303560static size_t get_output_period_size(uint32_t sample_rate,
3561 audio_format_t format,
3562 int channel_count,
3563 int duration /*in millisecs*/)
3564{
3565 size_t size = 0;
3566 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3567
3568 if ((duration == 0) || (sample_rate == 0) ||
3569 (bytes_per_sample == 0) || (channel_count == 0)) {
3570 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3571 bytes_per_sample, channel_count);
3572 return -EINVAL;
3573 }
3574
3575 size = (sample_rate *
3576 duration *
3577 bytes_per_sample *
3578 channel_count) / 1000;
3579 /*
3580 * To have same PCM samples for all channels, the buffer size requires to
3581 * be multiple of (number of channels * bytes per sample)
3582 * For writes to succeed, the buffer must be written at address which is multiple of 32
3583 */
3584 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3585
3586 return (size/(channel_count * bytes_per_sample));
3587}
3588
Zhou Song48453a02018-01-10 17:50:59 +08003589static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303590{
3591 uint64_t actual_frames_rendered = 0;
3592 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3593
3594 /* This adjustment accounts for buffering after app processor.
3595 * It is based on estimated DSP latency per use case, rather than exact.
3596 */
3597 int64_t platform_latency = platform_render_latency(out->usecase) *
3598 out->sample_rate / 1000000LL;
3599
Zhou Song48453a02018-01-10 17:50:59 +08003600 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303601 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3602 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3603 * hence only estimate.
3604 */
3605 int64_t signed_frames = out->written - kernel_buffer_size;
3606
3607 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3608
Zhou Song48453a02018-01-10 17:50:59 +08003609 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303610 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003611 if (timestamp != NULL )
3612 *timestamp = out->writeAt;
3613 } else if (timestamp != NULL) {
3614 clock_gettime(CLOCK_MONOTONIC, timestamp);
3615 }
3616 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303617
3618 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3619 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3620 (long long int)out->written, (int)kernel_buffer_size,
3621 audio_bytes_per_sample(out->compr_config.codec->format),
3622 popcount(out->channel_mask));
3623
3624 return actual_frames_rendered;
3625}
3626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3628{
3629 struct stream_out *out = (struct stream_out *)stream;
3630
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003631 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632}
3633
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003634static int out_set_sample_rate(struct audio_stream *stream __unused,
3635 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636{
3637 return -ENOSYS;
3638}
3639
3640static size_t out_get_buffer_size(const struct audio_stream *stream)
3641{
3642 struct stream_out *out = (struct stream_out *)stream;
3643
Varun Balaraje49253e2017-07-06 19:48:56 +05303644 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303645 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303646 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303647 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3648 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3649 else
3650 return out->compr_config.fragment_size;
3651 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003652 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003653 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3654 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 +05303655 else if (is_offload_usecase(out->usecase) &&
3656 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303657 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003658
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003659 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003660 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003661}
3662
3663static uint32_t out_get_channels(const struct audio_stream *stream)
3664{
3665 struct stream_out *out = (struct stream_out *)stream;
3666
3667 return out->channel_mask;
3668}
3669
3670static audio_format_t out_get_format(const struct audio_stream *stream)
3671{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003672 struct stream_out *out = (struct stream_out *)stream;
3673
3674 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675}
3676
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003677static int out_set_format(struct audio_stream *stream __unused,
3678 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679{
3680 return -ENOSYS;
3681}
3682
3683static int out_standby(struct audio_stream *stream)
3684{
3685 struct stream_out *out = (struct stream_out *)stream;
3686 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003687 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003688
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303689 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3690 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003692 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003694 if (adev->adm_deregister_stream)
3695 adev->adm_deregister_stream(adev->adm_data, out->handle);
3696
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003697 if (is_offload_usecase(out->usecase))
3698 stop_compressed_output_l(out);
3699
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003700 pthread_mutex_lock(&adev->lock);
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05303701
3702 amplifier_output_stream_standby((struct audio_stream_out *) stream);
3703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003705 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3706 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303707 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003708 pthread_mutex_unlock(&adev->lock);
3709 pthread_mutex_unlock(&out->lock);
3710 ALOGD("VOIP output entered standby");
3711 return 0;
3712 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003713 if (out->pcm) {
3714 pcm_close(out->pcm);
3715 out->pcm = NULL;
3716 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003717 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3718 do_stop = out->playback_started;
3719 out->playback_started = false;
3720 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003721 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003722 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303723 out->send_next_track_params = false;
3724 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003725 out->gapless_mdata.encoder_delay = 0;
3726 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003727 if (out->compr != NULL) {
3728 compress_close(out->compr);
3729 out->compr = NULL;
3730 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003731 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003732 if (do_stop) {
3733 stop_output_stream(out);
3734 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003735 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 }
3737 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303738 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739 return 0;
3740}
3741
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303742static int out_on_error(struct audio_stream *stream)
3743{
3744 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003745 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303746
3747 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003748 // always send CMD_ERROR for offload streams, this
3749 // is needed e.g. when SSR happens within compress_open
3750 // since the stream is active, offload_callback_thread is also active.
3751 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3752 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003753 }
3754 pthread_mutex_unlock(&out->lock);
3755
3756 status = out_standby(&out->stream.common);
3757
3758 lock_output_stream(out);
3759 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003760 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303761 }
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05303762
3763 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
3764 ALOGD("Setting previous card status if offline");
3765 out->prev_card_status_offline = true;
3766 }
3767
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303768 pthread_mutex_unlock(&out->lock);
3769
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003770 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303771}
3772
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303773/*
3774 *standby implementation without locks, assumes that the callee already
3775 *has taken adev and out lock.
3776 */
3777int out_standby_l(struct audio_stream *stream)
3778{
3779 struct stream_out *out = (struct stream_out *)stream;
3780 struct audio_device *adev = out->dev;
3781
3782 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3783 stream, out->usecase, use_case_table[out->usecase]);
3784
3785 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003786 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303787 if (adev->adm_deregister_stream)
3788 adev->adm_deregister_stream(adev->adm_data, out->handle);
3789
3790 if (is_offload_usecase(out->usecase))
3791 stop_compressed_output_l(out);
3792
3793 out->standby = true;
3794 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3795 voice_extn_compress_voip_close_output_stream(stream);
3796 out->started = 0;
3797 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003798 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303799 return 0;
3800 } else if (!is_offload_usecase(out->usecase)) {
3801 if (out->pcm) {
3802 pcm_close(out->pcm);
3803 out->pcm = NULL;
3804 }
3805 } else {
3806 ALOGD("copl(%p):standby", out);
3807 out->send_next_track_params = false;
3808 out->is_compr_metadata_avail = false;
3809 out->gapless_mdata.encoder_delay = 0;
3810 out->gapless_mdata.encoder_padding = 0;
3811 if (out->compr != NULL) {
3812 compress_close(out->compr);
3813 out->compr = NULL;
3814 }
3815 }
3816 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003817 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303818 }
3819 ALOGD("%s: exit", __func__);
3820 return 0;
3821}
3822
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003823static int out_dump(const struct audio_stream *stream __unused,
3824 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003825{
3826 return 0;
3827}
3828
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003829static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3830{
3831 int ret = 0;
3832 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003833
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003834 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003835 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003836 return -EINVAL;
3837 }
3838
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303839 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003840
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003841 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3842 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303843 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003844 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003845 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3846 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303847 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003848 }
3849
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003850 ALOGV("%s new encoder delay %u and padding %u", __func__,
3851 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3852
3853 return 0;
3854}
3855
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003856static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3857{
3858 return out == adev->primary_output || out == adev->voice_tx_output;
3859}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003860
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303861// note: this call is safe only if the stream_cb is
3862// removed first in close_output_stream (as is done now).
3863static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3864{
3865 if (!stream || !parms)
3866 return;
3867
3868 struct stream_out *out = (struct stream_out *)stream;
3869 struct audio_device *adev = out->dev;
3870
3871 card_status_t status;
3872 int card;
3873 if (parse_snd_card_status(parms, &card, &status) < 0)
3874 return;
3875
3876 pthread_mutex_lock(&adev->lock);
3877 bool valid_cb = (card == adev->snd_card);
3878 pthread_mutex_unlock(&adev->lock);
3879
3880 if (!valid_cb)
3881 return;
3882
3883 lock_output_stream(out);
3884 if (out->card_status != status)
3885 out->card_status = status;
3886 pthread_mutex_unlock(&out->lock);
3887
3888 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3889 use_case_table[out->usecase],
3890 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3891
Aditya Bavanari9aa0b922019-02-05 17:44:57 +05303892 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303893 out_on_error(stream);
Aditya Bavanari9aa0b922019-02-05 17:44:57 +05303894 if (voice_is_call_state_active(adev) &&
3895 out == adev->primary_output) {
3896 ALOGD("%s: SSR/PDR occurred, end all calls", __func__);
3897 pthread_mutex_lock(&adev->lock);
3898 voice_stop_call(adev);
3899 adev->mode = AUDIO_MODE_NORMAL;
3900 pthread_mutex_unlock(&adev->lock);
3901 }
3902 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303903 return;
3904}
3905
Kevin Rocardfce19002017-08-07 19:21:36 -07003906static int get_alive_usb_card(struct str_parms* parms) {
3907 int card;
3908 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
3909 !audio_extn_usb_alive(card)) {
3910 return card;
3911 }
3912 return -ENODEV;
3913}
3914
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3916{
3917 struct stream_out *out = (struct stream_out *)stream;
3918 struct audio_device *adev = out->dev;
3919 struct str_parms *parms;
3920 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003921 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303922 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003923 bool reconfig = false;
3924 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003925
sangwoobc677242013-08-08 16:53:43 +09003926 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003927 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303929 if (!parms)
3930 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003931 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3932 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003933 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003934 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003935 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003937 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003938 * When HDMI cable is unplugged the music playback is paused and
3939 * the policy manager sends routing=0. But the audioflinger continues
3940 * to write data until standby time (3sec). As the HDMI core is
3941 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003942 * Avoid this by routing audio to speaker until standby.
3943 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003944 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3945 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303946 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003947 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3948 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003949 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303950 /*
3951 * When A2DP is disconnected the
3952 * music playback is paused and the policy manager sends routing=0
3953 * But the audioflingercontinues to write data until standby time
3954 * (3sec). As BT is turned off, the write gets blocked.
3955 * Avoid this by routing audio to speaker until standby.
3956 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003957 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07003958 (val == AUDIO_DEVICE_NONE) &&
3959 !audio_extn_a2dp_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303960 val = AUDIO_DEVICE_OUT_SPEAKER;
3961 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05303962 /*
3963 * When USB headset is disconnected the music platback paused
3964 * and the policy manager send routing=0. But if the USB is connected
3965 * back before the standby time, AFE is not closed and opened
3966 * when USB is connected back. So routing to speker will guarantee
3967 * AFE reconfiguration and AFE will be opend once USB is connected again
3968 */
3969 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
3970 (val == AUDIO_DEVICE_NONE) &&
3971 !audio_extn_usb_connected(parms)) {
3972 val = AUDIO_DEVICE_OUT_SPEAKER;
3973 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303974 /* To avoid a2dp to sco overlapping / BT device improper state
3975 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303976 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303977 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3978 if (!audio_extn_a2dp_is_ready()) {
3979 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3980 //combo usecase just by pass a2dp
3981 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303982 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303983 } else {
3984 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3985 /* update device to a2dp and don't route as BT returned error
3986 * However it is still possible a2dp routing called because
3987 * of current active device disconnection (like wired headset)
3988 */
3989 out->devices = val;
3990 pthread_mutex_unlock(&out->lock);
3991 pthread_mutex_unlock(&adev->lock);
3992 goto error;
3993 }
3994 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303995 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003996
3997 audio_devices_t new_dev = val;
3998
3999 // Workaround: If routing to an non existing usb device, fail gracefully
4000 // The routing request will otherwise block during 10 second
4001 int card;
4002 if (audio_is_usb_out_device(new_dev) &&
4003 (card = get_alive_usb_card(parms)) >= 0) {
4004
4005 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4006 pthread_mutex_unlock(&adev->lock);
4007 pthread_mutex_unlock(&out->lock);
4008 ret = -ENOSYS;
4009 goto routing_fail;
4010 }
4011
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004012 /*
4013 * select_devices() call below switches all the usecases on the same
4014 * backend to the new device. Refer to check_usecases_codec_backend() in
4015 * the select_devices(). But how do we undo this?
4016 *
4017 * For example, music playback is active on headset (deep-buffer usecase)
4018 * and if we go to ringtones and select a ringtone, low-latency usecase
4019 * will be started on headset+speaker. As we can't enable headset+speaker
4020 * and headset devices at the same time, select_devices() switches the music
4021 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4022 * So when the ringtone playback is completed, how do we undo the same?
4023 *
4024 * We are relying on the out_set_parameters() call on deep-buffer output,
4025 * once the ringtone playback is ended.
4026 * NOTE: We should not check if the current devices are same as new devices.
4027 * Because select_devices() must be called to switch back the music
4028 * playback to headset.
4029 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004030 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004031 audio_devices_t new_dev = val;
4032 bool same_dev = out->devices == new_dev;
4033 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004034
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004035 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004036 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004037 if (adev->mode == AUDIO_MODE_IN_CALL) {
4038 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004039 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4040 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4041 audio_extn_usb_set_service_interval(true /*playback*/,
4042 service_interval,
4043 &reconfig);
4044 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4045 }
4046 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004047 }
4048 } else {
4049 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004050 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004051 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004052 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004053
4054 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004055 if (!same_dev) {
4056 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304057 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4058 adev->perf_lock_opts,
4059 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004060 if (adev->adm_on_routing_change)
4061 adev->adm_on_routing_change(adev->adm_data,
4062 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004063 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304064 if (!bypass_a2dp) {
4065 select_devices(adev, out->usecase);
4066 } else {
4067 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
4068 select_devices(adev, out->usecase);
4069 out->devices = new_dev;
4070 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004071
4072 if (!same_dev) {
4073 // on device switch force swap, lower functions will make sure
4074 // to check if swap is allowed or not.
4075 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304076 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004077 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304078 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4079 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08004080 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304081 pthread_mutex_lock(&out->compr_mute_lock);
4082 out->a2dp_compress_mute = false;
4083 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4084 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004085 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4086 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304087 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004088 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004089 }
4090
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004091 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004092 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004094 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004095
4096 if (out == adev->primary_output) {
4097 pthread_mutex_lock(&adev->lock);
4098 audio_extn_set_parameters(adev, parms);
4099 pthread_mutex_unlock(&adev->lock);
4100 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004101 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004102 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004103 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004104
4105 audio_extn_dts_create_state_notifier_node(out->usecase);
4106 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4107 popcount(out->channel_mask),
4108 out->playback_started);
4109
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004110 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004111 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004112
Surendar Karka5a18a7a2018-04-26 11:28:38 +05304113 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4114 sizeof(value));
4115 if (err >= 0) {
4116 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4117 audio_extn_send_dual_mono_mixing_coefficients(out);
4118 }
4119
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304120 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4121 if (err >= 0) {
4122 strlcpy(out->profile, value, sizeof(out->profile));
4123 ALOGV("updating stream profile with value '%s'", out->profile);
4124 lock_output_stream(out);
4125 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4126 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004127 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304128 out->sample_rate, out->bit_width,
4129 out->channel_mask, out->profile,
4130 &out->app_type_cfg);
4131 pthread_mutex_unlock(&out->lock);
4132 }
4133
Alexy Joseph98988832017-01-13 14:56:59 -08004134 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004135 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4136 // and vendor.audio.hal.output.suspend.supported is set to true
4137 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004138 //check suspend parameter only for low latency and if the property
4139 //is enabled
4140 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4141 ALOGI("%s: got suspend_playback %s", __func__, value);
4142 lock_output_stream(out);
4143 if (!strncmp(value, "false", 5)) {
4144 //suspend_playback=false is supposed to set QOS value back to 75%
4145 //the mixer control sent with value Enable will achieve that
4146 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4147 } else if (!strncmp (value, "true", 4)) {
4148 //suspend_playback=true is supposed to remove QOS value
4149 //resetting the mixer control will set the default value
4150 //for the mixer control which is Disable and this removes the QOS vote
4151 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4152 } else {
4153 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4154 " got %s", __func__, value);
4155 ret = -1;
4156 }
4157
4158 if (ret != 0) {
4159 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4160 __func__, out->pm_qos_mixer_path, ret);
4161 }
4162
4163 pthread_mutex_unlock(&out->lock);
4164 }
4165 }
4166 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304168error:
Eric Laurent994a6932013-07-17 11:51:42 -07004169 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004170 return ret;
4171}
4172
Ramjee Singhacef98f2019-06-28 11:01:25 +05304173#if ANDROID_PLATFORM_SDK_VERSION >= 29
4174static int in_set_microphone_direction(const struct audio_stream_in *stream,
4175 audio_microphone_direction_t dir) {
4176 int ret_val = -ENOSYS;
4177 (void)stream;
4178 (void)dir;
4179 ALOGV("---- in_set_microphone_direction()");
4180 return ret_val;
4181}
4182
4183static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
4184 int ret_val = -ENOSYS;
4185 (void)zoom;
4186 (void)stream;
4187 ALOGV("---- in_set_microphone_field_dimension()");
4188 return ret_val;
4189}
4190#endif
4191
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004192static bool stream_get_parameter_channels(struct str_parms *query,
4193 struct str_parms *reply,
4194 audio_channel_mask_t *supported_channel_masks) {
4195 int ret = -1;
4196 char value[512];
4197 bool first = true;
4198 size_t i, j;
4199
4200 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4201 ret = 0;
4202 value[0] = '\0';
4203 i = 0;
4204 while (supported_channel_masks[i] != 0) {
4205 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4206 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4207 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304208 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004209
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304210 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004211 first = false;
4212 break;
4213 }
4214 }
4215 i++;
4216 }
4217 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4218 }
4219 return ret == 0;
4220}
4221
4222static bool stream_get_parameter_formats(struct str_parms *query,
4223 struct str_parms *reply,
4224 audio_format_t *supported_formats) {
4225 int ret = -1;
4226 char value[256];
4227 size_t i, j;
4228 bool first = true;
4229
4230 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4231 ret = 0;
4232 value[0] = '\0';
4233 i = 0;
4234 while (supported_formats[i] != 0) {
4235 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4236 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4237 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304238 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004239 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304240 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004241 first = false;
4242 break;
4243 }
4244 }
4245 i++;
4246 }
4247 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4248 }
4249 return ret == 0;
4250}
4251
4252static bool stream_get_parameter_rates(struct str_parms *query,
4253 struct str_parms *reply,
4254 uint32_t *supported_sample_rates) {
4255
4256 int i;
4257 char value[256];
4258 int ret = -1;
4259 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4260 ret = 0;
4261 value[0] = '\0';
4262 i=0;
4263 int cursor = 0;
4264 while (supported_sample_rates[i]) {
4265 int avail = sizeof(value) - cursor;
4266 ret = snprintf(value + cursor, avail, "%s%d",
4267 cursor > 0 ? "|" : "",
4268 supported_sample_rates[i]);
4269 if (ret < 0 || ret >= avail) {
4270 // if cursor is at the last element of the array
4271 // overwrite with \0 is duplicate work as
4272 // snprintf already put a \0 in place.
4273 // else
4274 // we had space to write the '|' at value[cursor]
4275 // (which will be overwritten) or no space to fill
4276 // the first element (=> cursor == 0)
4277 value[cursor] = '\0';
4278 break;
4279 }
4280 cursor += ret;
4281 ++i;
4282 }
4283 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4284 value);
4285 }
4286 return ret >= 0;
4287}
4288
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004289static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4290{
4291 struct stream_out *out = (struct stream_out *)stream;
4292 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004293 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004294 char value[256];
4295 struct str_parms *reply = str_parms_create();
4296 size_t i, j;
4297 int ret;
4298 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004299
4300 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004301 if (reply) {
4302 str_parms_destroy(reply);
4303 }
4304 if (query) {
4305 str_parms_destroy(query);
4306 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004307 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4308 return NULL;
4309 }
4310
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004311 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004312 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4313 if (ret >= 0) {
4314 value[0] = '\0';
4315 i = 0;
4316 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004317 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4318 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004319 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004320 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004322 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004323 first = false;
4324 break;
4325 }
4326 }
4327 i++;
4328 }
4329 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4330 str = str_parms_to_str(reply);
4331 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004332 voice_extn_out_get_parameters(out, query, reply);
4333 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004334 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004335
Alexy Joseph62142aa2015-11-16 15:10:34 -08004336
4337 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4338 if (ret >= 0) {
4339 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304340 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4341 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004342 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304343 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004344 } else {
4345 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304346 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004347 }
4348 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004349 if (str)
4350 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004351 str = str_parms_to_str(reply);
4352 }
4353
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004354 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4355 if (ret >= 0) {
4356 value[0] = '\0';
4357 i = 0;
4358 first = true;
4359 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004360 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4361 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004362 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004363 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004364 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004365 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004366 first = false;
4367 break;
4368 }
4369 }
4370 i++;
4371 }
4372 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004373 if (str)
4374 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004375 str = str_parms_to_str(reply);
4376 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004377
4378 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4379 if (ret >= 0) {
4380 value[0] = '\0';
4381 i = 0;
4382 first = true;
4383 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004384 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4385 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004386 if (!first) {
4387 strlcat(value, "|", sizeof(value));
4388 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004389 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004390 first = false;
4391 break;
4392 }
4393 }
4394 i++;
4395 }
4396 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4397 if (str)
4398 free(str);
4399 str = str_parms_to_str(reply);
4400 }
4401
Alexy Joseph98988832017-01-13 14:56:59 -08004402 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4403 //only low latency track supports suspend_resume
4404 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004405 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004406 if (str)
4407 free(str);
4408 str = str_parms_to_str(reply);
4409 }
4410
4411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004412 str_parms_destroy(query);
4413 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004414 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004415 return str;
4416}
4417
4418static uint32_t out_get_latency(const struct audio_stream_out *stream)
4419{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004420 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004421 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004422 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423
Alexy Josephaa54c872014-12-03 02:46:47 -08004424 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304425 lock_output_stream(out);
4426 latency = audio_extn_utils_compress_get_dsp_latency(out);
4427 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004428 } else if ((out->realtime) ||
4429 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004430 // since the buffer won't be filled up faster than realtime,
4431 // return a smaller number
4432 if (out->config.rate)
4433 period_ms = (out->af_period_multiplier * out->config.period_size *
4434 1000) / (out->config.rate);
4435 else
4436 period_ms = 0;
4437 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004438 } else {
4439 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004440 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004441 }
4442
yidongh0515e042017-07-06 15:00:34 +08004443 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004444 latency += audio_extn_a2dp_get_encoder_latency();
4445
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304446 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004447 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004448}
4449
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304450static float AmpToDb(float amplification)
4451{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304452 float db = DSD_VOLUME_MIN_DB;
4453 if (amplification > 0) {
4454 db = 20 * log10(amplification);
4455 if(db < DSD_VOLUME_MIN_DB)
4456 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304457 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304458 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304459}
4460
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004461static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4462 float right)
4463{
4464 struct stream_out *out = (struct stream_out *)stream;
4465 long volume = 0;
4466 char mixer_ctl_name[128] = "";
4467 struct audio_device *adev = out->dev;
4468 struct mixer_ctl *ctl = NULL;
4469 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4470 PCM_PLAYBACK);
4471
4472 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4473 "Playback %d Volume", pcm_device_id);
4474 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4475 if (!ctl) {
4476 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4477 __func__, mixer_ctl_name);
4478 return -EINVAL;
4479 }
4480 if (left != right)
4481 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4482 __func__, left, right);
4483 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4484 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4485 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4486 __func__, mixer_ctl_name, volume);
4487 return -EINVAL;
4488 }
4489 return 0;
4490}
4491
4492
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304493static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4494 float right)
4495{
4496 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304497 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304498 char mixer_ctl_name[128];
4499 struct audio_device *adev = out->dev;
4500 struct mixer_ctl *ctl;
4501 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4502 PCM_PLAYBACK);
4503
4504 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4505 "Compress Playback %d Volume", pcm_device_id);
4506 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4507 if (!ctl) {
4508 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4509 __func__, mixer_ctl_name);
4510 return -EINVAL;
4511 }
4512 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4513 __func__, mixer_ctl_name, left, right);
4514 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4515 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4516 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4517
4518 return 0;
4519}
4520
Zhou Song2b8f28f2017-09-11 10:51:38 +08004521static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4522 float right)
4523{
4524 struct stream_out *out = (struct stream_out *)stream;
4525 char mixer_ctl_name[] = "App Type Gain";
4526 struct audio_device *adev = out->dev;
4527 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304528 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004529
4530 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4531 if (!ctl) {
4532 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4533 __func__, mixer_ctl_name);
4534 return -EINVAL;
4535 }
4536
4537 set_values[0] = 0; //0: Rx Session 1:Tx Session
4538 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304539 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4540 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004541
4542 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4543 return 0;
4544}
4545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004546static int out_set_volume(struct audio_stream_out *stream, float left,
4547 float right)
4548{
Eric Laurenta9024de2013-04-04 09:19:12 -07004549 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004550 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304551 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004552
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004553 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
4554
Eric Laurenta9024de2013-04-04 09:19:12 -07004555 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4556 /* only take left channel into account: the API is for stereo anyway */
4557 out->muted = (left == 0.0f);
4558 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004559 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304560 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004561 /*
4562 * Set mute or umute on HDMI passthrough stream.
4563 * Only take left channel into account.
4564 * Mute is 0 and unmute 1
4565 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304566 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304567 } else if (out->format == AUDIO_FORMAT_DSD){
4568 char mixer_ctl_name[128] = "DSD Volume";
4569 struct audio_device *adev = out->dev;
4570 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4571
4572 if (!ctl) {
4573 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4574 __func__, mixer_ctl_name);
4575 return -EINVAL;
4576 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304577 volume[0] = (long)(AmpToDb(left));
4578 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304579 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4580 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004581 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304582 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004583 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304584 if (!out->a2dp_compress_mute)
4585 ret = out_set_compr_volume(stream, left, right);
4586 out->volume_l = left;
4587 out->volume_r = right;
4588 pthread_mutex_unlock(&out->compr_mute_lock);
4589 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004590 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004591 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004592 if (!out->standby)
4593 ret = out_set_voip_volume(stream, left, right);
4594 out->volume_l = left;
4595 out->volume_r = right;
4596 return ret;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004597 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4598 ALOGV("%s: MMAP set volume called", __func__);
4599 if (!out->standby)
4600 ret = out_set_mmap_volume(stream, left, right);
4601 out->volume_l = left;
4602 out->volume_r = right;
4603 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004604 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004606 return -ENOSYS;
4607}
4608
Zhou Songc9672822017-08-16 16:01:39 +08004609static void update_frames_written(struct stream_out *out, size_t bytes)
4610{
4611 size_t bpf = 0;
4612
4613 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4614 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4615 bpf = 1;
4616 else if (!is_offload_usecase(out->usecase))
4617 bpf = audio_bytes_per_sample(out->format) *
4618 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004619
4620 pthread_mutex_lock(&out->position_query_lock);
4621 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004622 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004623 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4624 }
4625 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004626}
4627
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004628static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4629 size_t bytes)
4630{
4631 struct stream_out *out = (struct stream_out *)stream;
4632 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004633 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304634 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004635 const size_t frame_size = audio_stream_out_frame_size(stream);
4636 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05304637 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004638
Haynes Mathew George380745d2017-10-04 15:27:45 -07004639 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004640 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304641
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304642 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004643
Dhananjay Kumarac341582017-02-23 23:42:25 +05304644 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304645 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304646 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4647 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004648 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304649 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304650 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304651 ALOGD(" %s: sound card is not active/SSR state", __func__);
4652 ret= -EIO;
4653 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304654 }
4655 }
4656
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304657 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304658 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304659 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304660 goto exit;
4661 }
4662
Haynes Mathew George16081042017-05-31 17:16:49 -07004663 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4664 ret = -EINVAL;
4665 goto exit;
4666 }
4667
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304668 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4669 !out->is_iec61937_info_available) {
4670
4671 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4672 out->is_iec61937_info_available = true;
4673 } else if (audio_extn_passthru_is_enabled()) {
4674 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304675 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304676
4677 if((out->format == AUDIO_FORMAT_DTS) ||
4678 (out->format == AUDIO_FORMAT_DTS_HD)) {
4679 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4680 buffer, bytes);
4681 if (ret) {
4682 if (ret != -ENOSYS) {
4683 out->is_iec61937_info_available = false;
4684 ALOGD("iec61937 transmission info not yet updated retry");
4685 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304686 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304687 /* if stream has started and after that there is
4688 * stream config change (iec transmission config)
4689 * then trigger select_device to update backend configuration.
4690 */
4691 out->stream_config_changed = true;
4692 pthread_mutex_lock(&adev->lock);
4693 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304694 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4695 ret = -EINVAL;
4696 goto exit;
4697 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304698 pthread_mutex_unlock(&adev->lock);
4699 out->stream_config_changed = false;
4700 out->is_iec61937_info_available = true;
4701 }
4702 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304703
Garmond Leung317cbf12017-09-13 16:20:50 -07004704 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304705 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4706 (out->is_iec61937_info_available == true)) {
4707 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4708 ret = -EINVAL;
4709 goto exit;
4710 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304711 }
4712 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304713
4714 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4715 (audio_extn_a2dp_is_suspended())) {
4716 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4717 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304718 ret = -EIO;
4719 goto exit;
4720 }
4721 }
4722 }
4723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004724 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004725 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004726 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004727 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4728 ret = voice_extn_compress_voip_start_output_stream(out);
4729 else
4730 ret = start_output_stream(out);
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05304731
4732 if (ret == 0)
4733 amplifier_output_stream_start(stream,
4734 is_offload_usecase(out->usecase));
4735
Eric Laurent150dbfe2013-02-27 14:31:02 -08004736 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004737 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004738 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004739 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004740 goto exit;
4741 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304742 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004743 if (last_known_cal_step != -1) {
4744 ALOGD("%s: retry previous failed cal level set", __func__);
4745 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304746 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004747 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304748
4749 if ((out->is_iec61937_info_available == true) &&
4750 (audio_extn_passthru_is_passthrough_stream(out))&&
4751 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4752 ret = -EINVAL;
4753 goto exit;
4754 }
Surendar Karka5a18a7a2018-04-26 11:28:38 +05304755 if (out->set_dual_mono)
4756 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004757 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004758
Ashish Jain81eb2a82015-05-13 10:52:34 +05304759 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004760 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304761 adev->is_channel_status_set = true;
4762 }
4763
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05304764 if ((adev->use_old_pspd_mix_ctrl == true) &&
4765 (out->pspd_coeff_sent == false)) {
4766 /*
4767 * Need to resend pspd coefficients after stream started for
4768 * older kernel version as it does not save the coefficients
4769 * and also stream has to be started for coeff to apply.
4770 */
4771 usecase = get_usecase_from_list(adev, out->usecase);
4772 if (usecase != NULL) {
4773 audio_extn_set_custom_mtmx_params(adev, usecase, true);
4774 out->pspd_coeff_sent = true;
4775 }
4776 }
4777
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004778 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004779 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004780 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004781 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004782 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4783 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304784 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4785 ALOGD("copl(%p):send next track params in gapless", out);
4786 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4787 out->send_next_track_params = false;
4788 out->is_compr_metadata_avail = false;
4789 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004790 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304791 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304792 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004793
Ashish Jain83a6cc22016-06-28 14:34:17 +05304794 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304795 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304796 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304797 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004798 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304799 return -EINVAL;
4800 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304801 audio_format_t dst_format = out->hal_op_format;
4802 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304803
4804 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4805 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4806
Ashish Jain83a6cc22016-06-28 14:34:17 +05304807 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304808 dst_format,
4809 buffer,
4810 src_format,
4811 frames);
4812
Ashish Jain83a6cc22016-06-28 14:34:17 +05304813 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304814 bytes_to_write);
4815
4816 /*Convert written bytes in audio flinger format*/
4817 if (ret > 0)
4818 ret = ((ret * format_to_bitwidth_table[out->format]) /
4819 format_to_bitwidth_table[dst_format]);
4820 }
4821 } else
4822 ret = compress_write(out->compr, buffer, bytes);
4823
Zhou Songc9672822017-08-16 16:01:39 +08004824 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4825 update_frames_written(out, bytes);
4826
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304827 if (ret < 0)
4828 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08004829 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304830 /*msg to cb thread only if non blocking write is enabled*/
4831 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304832 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004833 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304834 } else if (-ENETRESET == ret) {
4835 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304836 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304837 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304838 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004839 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304840 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004841 }
Ashish Jain5106d362016-05-11 19:23:33 +05304842
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304843 /* Call compr start only when non-zero bytes of data is there to be rendered */
4844 if (!out->playback_started && ret > 0) {
4845 int status = compress_start(out->compr);
4846 if (status < 0) {
4847 ret = status;
4848 ALOGE("%s: compr start failed with err %d", __func__, errno);
4849 goto exit;
4850 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004851 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004852 out->playback_started = 1;
4853 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004854
4855 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4856 popcount(out->channel_mask),
4857 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004858 }
4859 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004860 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004861 return ret;
4862 } else {
4863 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004864 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004865 if (out->muted)
4866 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004867 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
4868 __func__, frames, frame_size, bytes_to_write);
4869
Arun Mirpuridbef0c72018-09-12 18:36:10 -07004870 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4871 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004872 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4873 int16_t *src = (int16_t *)buffer;
4874 int16_t *dst = (int16_t *)buffer;
4875
4876 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
4877 out->format != AUDIO_FORMAT_PCM_16_BIT,
4878 "out_write called for incall music use case with wrong properties");
4879
4880 /*
4881 * FIXME: this can be removed once audio flinger mixer supports
4882 * mono output
4883 */
4884
4885 /*
4886 * Code below goes over each frame in the buffer and adds both
4887 * L and R samples and then divides by 2 to convert to mono
4888 */
4889 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
4890 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
4891 }
4892 bytes_to_write /= 2;
4893 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004894
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304895 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004896
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004897 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004898
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004899 if (out->config.rate)
4900 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4901 out->config.rate;
4902
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004903 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004904 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4905
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004906 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004907 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004908 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304909 out->convert_buffer != NULL) {
4910
4911 memcpy_by_audio_format(out->convert_buffer,
4912 out->hal_op_format,
4913 buffer,
4914 out->hal_ip_format,
4915 out->config.period_size * out->config.channels);
4916
4917 ret = pcm_write(out->pcm, out->convert_buffer,
4918 (out->config.period_size *
4919 out->config.channels *
4920 format_to_bitwidth_table[out->hal_op_format]));
4921 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304922 /*
4923 * To avoid underrun in DSP when the application is not pumping
4924 * data at required rate, check for the no. of bytes and ignore
4925 * pcm_write if it is less than actual buffer size.
4926 * It is a work around to a change in compress VOIP driver.
4927 */
4928 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4929 bytes < (out->config.period_size * out->config.channels *
4930 audio_bytes_per_sample(out->format))) {
4931 size_t voip_buf_size =
4932 out->config.period_size * out->config.channels *
4933 audio_bytes_per_sample(out->format);
4934 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4935 __func__, bytes, voip_buf_size);
4936 usleep(((uint64_t)voip_buf_size - bytes) *
4937 1000000 / audio_stream_out_frame_size(stream) /
4938 out_get_sample_rate(&out->stream.common));
4939 ret = 0;
4940 } else
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004941 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304942 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004943
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004944 release_out_focus(out);
4945
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304946 if (ret < 0)
4947 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004948 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304949 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004950 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004951 }
4952
4953exit:
Zhou Songc9672822017-08-16 16:01:39 +08004954 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304955 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304956 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304957 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004958 pthread_mutex_unlock(&out->lock);
4959
4960 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004961 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004962 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304963 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304964 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304965 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304966 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304967 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304968 out->standby = true;
4969 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304970 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304971 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4972 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4973 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004974
4975 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05304976 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004977 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004978 return ret;
4979 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004980 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004981 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004982 return bytes;
4983}
4984
4985static int out_get_render_position(const struct audio_stream_out *stream,
4986 uint32_t *dsp_frames)
4987{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004988 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004989
4990 if (dsp_frames == NULL)
4991 return -EINVAL;
4992
4993 *dsp_frames = 0;
4994 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004995 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304996
4997 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4998 * this operation and adev_close_output_stream(where out gets reset).
4999 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305000 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005001 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305002 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005003 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305004 return 0;
5005 }
5006
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005007 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305008 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305009 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005010 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305011 if (ret < 0)
5012 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005013 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305014 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005015 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305016 if (-ENETRESET == ret) {
5017 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305018 out->card_status = CARD_STATUS_OFFLINE;
5019 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305020 } else if(ret < 0) {
5021 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305022 ret = -EINVAL;
5023 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305024 /*
5025 * Handle corner case where compress session is closed during SSR
5026 * and timestamp is queried
5027 */
5028 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305029 ret = -EINVAL;
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05305030 } else if (out->prev_card_status_offline) {
5031 ALOGE("ERROR: previously sound card was offline,return error");
5032 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305033 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305034 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005035 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305036 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305037 pthread_mutex_unlock(&out->lock);
5038 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005039 } else if (audio_is_linear_pcm(out->format)) {
5040 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005041 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005042 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005043 } else
5044 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005045}
5046
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005047static int out_add_audio_effect(const struct audio_stream *stream __unused,
5048 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005049{
5050 return 0;
5051}
5052
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005053static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5054 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005055{
5056 return 0;
5057}
5058
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005059static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5060 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005061{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305062 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005063}
5064
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005065static int out_get_presentation_position(const struct audio_stream_out *stream,
5066 uint64_t *frames, struct timespec *timestamp)
5067{
5068 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305069 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005070 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005071
Ashish Jain5106d362016-05-11 19:23:33 +05305072 /* below piece of code is not guarded against any lock because audioFliner serializes
5073 * this operation and adev_close_output_stream( where out gets reset).
5074 */
5075 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305076 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005077 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305078 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5079 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5080 return 0;
5081 }
5082
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005083 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005084
Ashish Jain5106d362016-05-11 19:23:33 +05305085 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5086 ret = compress_get_tstamp(out->compr, &dsp_frames,
5087 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005088 // Adjustment accounts for A2dp encoder latency with offload usecases
5089 // Note: Encoder latency is returned in ms.
5090 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5091 unsigned long offset =
5092 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5093 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5094 }
Ashish Jain5106d362016-05-11 19:23:33 +05305095 ALOGVV("%s rendered frames %ld sample_rate %d",
5096 __func__, dsp_frames, out->sample_rate);
5097 *frames = dsp_frames;
5098 if (ret < 0)
5099 ret = -errno;
5100 if (-ENETRESET == ret) {
5101 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305102 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305103 ret = -EINVAL;
5104 } else
5105 ret = 0;
5106 /* this is the best we can do */
5107 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005108 } else {
5109 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005110 unsigned int avail;
5111 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5112 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5113 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5114 // This adjustment accounts for buffering after app processor.
5115 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005116 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005117 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005118
Weiyin Jiangd4633762018-03-16 12:05:03 +08005119 // Adjustment accounts for A2dp encoder latency with non offload usecases
5120 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5121 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5122 signed_frames -=
5123 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5124 }
5125
5126 // It would be unusual for this value to be negative, but check just in case ...
5127 if (signed_frames >= 0) {
5128 *frames = signed_frames;
5129 ret = 0;
5130 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005131 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305132 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305133 *frames = out->written;
5134 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05305135 if (is_offload_usecase(out->usecase))
5136 ret = -EINVAL;
5137 else
5138 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005139 }
5140 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005141 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005142 return ret;
5143}
5144
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005145static int out_set_callback(struct audio_stream_out *stream,
5146 stream_callback_t callback, void *cookie)
5147{
5148 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005149 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005150
5151 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005152 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005153 out->client_callback = callback;
5154 out->client_cookie = cookie;
5155 if (out->adsp_hdlr_stream_handle) {
5156 ret = audio_extn_adsp_hdlr_stream_set_callback(
5157 out->adsp_hdlr_stream_handle,
5158 callback,
5159 cookie);
5160 if (ret)
5161 ALOGW("%s:adsp hdlr callback registration failed %d",
5162 __func__, ret);
5163 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005164 pthread_mutex_unlock(&out->lock);
5165 return 0;
5166}
5167
5168static int out_pause(struct audio_stream_out* stream)
5169{
5170 struct stream_out *out = (struct stream_out *)stream;
5171 int status = -ENOSYS;
5172 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005173 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005174 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005175 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005176 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305177 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305178 status = compress_pause(out->compr);
5179
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005180 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005181
Mingming Yin21854652016-04-13 11:54:02 -07005182 if (audio_extn_passthru_is_active()) {
5183 ALOGV("offload use case, pause passthru");
5184 audio_extn_passthru_on_pause(out);
5185 }
5186
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305187 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005188 audio_extn_dts_notify_playback_state(out->usecase, 0,
5189 out->sample_rate, popcount(out->channel_mask),
5190 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005191 }
5192 pthread_mutex_unlock(&out->lock);
5193 }
5194 return status;
5195}
5196
5197static int out_resume(struct audio_stream_out* stream)
5198{
5199 struct stream_out *out = (struct stream_out *)stream;
5200 int status = -ENOSYS;
5201 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005202 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005203 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005204 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005205 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005206 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305207 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305208 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005209 }
5210 if (!status) {
5211 out->offload_state = OFFLOAD_STATE_PLAYING;
5212 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305213 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005214 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5215 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005216 }
5217 pthread_mutex_unlock(&out->lock);
5218 }
5219 return status;
5220}
5221
5222static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5223{
5224 struct stream_out *out = (struct stream_out *)stream;
5225 int status = -ENOSYS;
5226 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005227 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005228 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005229 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5230 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5231 else
5232 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5233 pthread_mutex_unlock(&out->lock);
5234 }
5235 return status;
5236}
5237
5238static int out_flush(struct audio_stream_out* stream)
5239{
5240 struct stream_out *out = (struct stream_out *)stream;
5241 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005242 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005243 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005244 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005245 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5246 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005247 } else {
5248 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5249 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005250 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005251 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005252 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005253 return 0;
5254 }
5255 return -ENOSYS;
5256}
5257
Haynes Mathew George16081042017-05-31 17:16:49 -07005258static int out_stop(const struct audio_stream_out* stream)
5259{
5260 struct stream_out *out = (struct stream_out *)stream;
5261 struct audio_device *adev = out->dev;
5262 int ret = -ENOSYS;
5263
5264 ALOGV("%s", __func__);
5265 pthread_mutex_lock(&adev->lock);
5266 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5267 out->playback_started && out->pcm != NULL) {
5268 pcm_stop(out->pcm);
5269 ret = stop_output_stream(out);
5270 out->playback_started = false;
5271 }
5272 pthread_mutex_unlock(&adev->lock);
5273 return ret;
5274}
5275
5276static int out_start(const struct audio_stream_out* stream)
5277{
5278 struct stream_out *out = (struct stream_out *)stream;
5279 struct audio_device *adev = out->dev;
5280 int ret = -ENOSYS;
5281
5282 ALOGV("%s", __func__);
5283 pthread_mutex_lock(&adev->lock);
5284 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5285 !out->playback_started && out->pcm != NULL) {
5286 ret = start_output_stream(out);
5287 if (ret == 0) {
5288 out->playback_started = true;
5289 }
5290 }
5291 pthread_mutex_unlock(&adev->lock);
5292 return ret;
5293}
5294
5295/*
5296 * Modify config->period_count based on min_size_frames
5297 */
5298static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5299{
5300 int periodCountRequested = (min_size_frames + config->period_size - 1)
5301 / config->period_size;
5302 int periodCount = MMAP_PERIOD_COUNT_MIN;
5303
5304 ALOGV("%s original config.period_size = %d config.period_count = %d",
5305 __func__, config->period_size, config->period_count);
5306
5307 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5308 periodCount *= 2;
5309 }
5310 config->period_count = periodCount;
5311
5312 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5313}
5314
5315static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5316 int32_t min_size_frames,
5317 struct audio_mmap_buffer_info *info)
5318{
5319 struct stream_out *out = (struct stream_out *)stream;
5320 struct audio_device *adev = out->dev;
5321 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005322 unsigned int offset1 = 0;
5323 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005324 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005325 uint32_t mmap_size;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005326 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005327
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005328 ALOGD("%s", __func__);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305329 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005330 pthread_mutex_lock(&adev->lock);
5331
Sharad Sangle90e613f2018-05-04 16:15:38 +05305332 if (CARD_STATUS_OFFLINE == out->card_status ||
5333 CARD_STATUS_OFFLINE == adev->card_status) {
5334 ALOGW("out->card_status or adev->card_status offline, try again");
5335 ret = -EIO;
5336 goto exit;
5337 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005338 if (info == NULL || min_size_frames == 0) {
5339 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5340 ret = -EINVAL;
5341 goto exit;
5342 }
5343 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5344 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5345 ret = -ENOSYS;
5346 goto exit;
5347 }
5348 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5349 if (out->pcm_device_id < 0) {
5350 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5351 __func__, out->pcm_device_id, out->usecase);
5352 ret = -EINVAL;
5353 goto exit;
5354 }
5355
5356 adjust_mmap_period_count(&out->config, min_size_frames);
5357
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005358 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005359 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5360 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5361 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305362 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
5363 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5364 out->card_status = CARD_STATUS_OFFLINE;
5365 adev->card_status = CARD_STATUS_OFFLINE;
5366 ret = -EIO;
5367 goto exit;
5368 }
5369
Haynes Mathew George16081042017-05-31 17:16:49 -07005370 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5371 step = "open";
5372 ret = -ENODEV;
5373 goto exit;
5374 }
5375 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5376 if (ret < 0) {
5377 step = "begin";
5378 goto exit;
5379 }
5380 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005381 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005382 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005383 ret = platform_get_mmap_data_fd(adev->platform,
5384 out->pcm_device_id, 0 /*playback*/,
5385 &info->shared_memory_fd,
5386 &mmap_size);
5387 if (ret < 0) {
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005388 // Fall back to non exclusive mode
5389 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5390 } else {
5391 if (mmap_size < buffer_size) {
5392 step = "mmap";
5393 goto exit;
5394 }
5395 // FIXME: indicate exclusive mode support by returning a negative buffer size
5396 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005397 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005398 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07005399
5400 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5401 if (ret < 0) {
5402 step = "commit";
5403 goto exit;
5404 }
5405
5406 out->standby = false;
5407 ret = 0;
5408
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005409 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005410 __func__, info->shared_memory_address, info->buffer_size_frames);
5411
5412exit:
5413 if (ret != 0) {
5414 if (out->pcm == NULL) {
5415 ALOGE("%s: %s - %d", __func__, step, ret);
5416 } else {
5417 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5418 pcm_close(out->pcm);
5419 out->pcm = NULL;
5420 }
5421 }
5422 pthread_mutex_unlock(&adev->lock);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305423 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005424 return ret;
5425}
5426
5427static int out_get_mmap_position(const struct audio_stream_out *stream,
5428 struct audio_mmap_position *position)
5429{
5430 struct stream_out *out = (struct stream_out *)stream;
5431 ALOGVV("%s", __func__);
5432 if (position == NULL) {
5433 return -EINVAL;
5434 }
5435 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005436 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005437 return -ENOSYS;
5438 }
5439 if (out->pcm == NULL) {
5440 return -ENOSYS;
5441 }
5442
5443 struct timespec ts = { 0, 0 };
5444 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5445 if (ret < 0) {
5446 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5447 return ret;
5448 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005449 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005450 return 0;
5451}
5452
5453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005454/** audio_stream_in implementation **/
5455static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5456{
5457 struct stream_in *in = (struct stream_in *)stream;
5458
5459 return in->config.rate;
5460}
5461
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005462static int in_set_sample_rate(struct audio_stream *stream __unused,
5463 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005464{
5465 return -ENOSYS;
5466}
5467
5468static size_t in_get_buffer_size(const struct audio_stream *stream)
5469{
5470 struct stream_in *in = (struct stream_in *)stream;
5471
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005472 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5473 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005474 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5475 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 -07005476 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5477 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305478 else if(audio_extn_cin_attached_usecase(in->usecase))
5479 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005480
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005481 return in->config.period_size * in->af_period_multiplier *
5482 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005483}
5484
5485static uint32_t in_get_channels(const struct audio_stream *stream)
5486{
5487 struct stream_in *in = (struct stream_in *)stream;
5488
5489 return in->channel_mask;
5490}
5491
5492static audio_format_t in_get_format(const struct audio_stream *stream)
5493{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005494 struct stream_in *in = (struct stream_in *)stream;
5495
5496 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005497}
5498
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005499static int in_set_format(struct audio_stream *stream __unused,
5500 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005501{
5502 return -ENOSYS;
5503}
5504
5505static int in_standby(struct audio_stream *stream)
5506{
5507 struct stream_in *in = (struct stream_in *)stream;
5508 struct audio_device *adev = in->dev;
5509 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305510 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5511 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005512 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305513
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005514 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005515 if (!in->standby && in->is_st_session) {
5516 ALOGD("%s: sound trigger pcm stop lab", __func__);
5517 audio_extn_sound_trigger_stop_lab(in);
5518 in->standby = 1;
5519 }
5520
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005521 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005522 if (adev->adm_deregister_stream)
5523 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5524
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005525 pthread_mutex_lock(&adev->lock);
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05305526
5527 amplifier_input_stream_standby((struct audio_stream_in *) stream);
5528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005529 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005530 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005531 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005532 voice_extn_compress_voip_close_input_stream(stream);
5533 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005534 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5535 do_stop = in->capture_started;
5536 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005537 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305538 if (audio_extn_cin_attached_usecase(in->usecase))
5539 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005540 }
5541
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005542 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005543 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005544 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005545 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005546 in->pcm = NULL;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005547 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005548
5549 if (do_stop)
5550 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005551 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005552 }
5553 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005554 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005555 return status;
5556}
5557
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005558static int in_dump(const struct audio_stream *stream __unused,
5559 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005560{
5561 return 0;
5562}
5563
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305564static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5565{
5566 if (!stream || !parms)
5567 return;
5568
5569 struct stream_in *in = (struct stream_in *)stream;
5570 struct audio_device *adev = in->dev;
5571
5572 card_status_t status;
5573 int card;
5574 if (parse_snd_card_status(parms, &card, &status) < 0)
5575 return;
5576
5577 pthread_mutex_lock(&adev->lock);
5578 bool valid_cb = (card == adev->snd_card);
5579 pthread_mutex_unlock(&adev->lock);
5580
5581 if (!valid_cb)
5582 return;
5583
5584 lock_input_stream(in);
5585 if (in->card_status != status)
5586 in->card_status = status;
5587 pthread_mutex_unlock(&in->lock);
5588
5589 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5590 use_case_table[in->usecase],
5591 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5592
5593 // a better solution would be to report error back to AF and let
5594 // it put the stream to standby
5595 if (status == CARD_STATUS_OFFLINE)
5596 in_standby(&in->stream.common);
5597
5598 return;
5599}
5600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005601static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5602{
5603 struct stream_in *in = (struct stream_in *)stream;
5604 struct audio_device *adev = in->dev;
5605 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005606 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005607 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005608
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305609 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005610 parms = str_parms_create_str(kvpairs);
5611
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305612 if (!parms)
5613 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005614 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005615 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005616
5617 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5618 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005619 val = atoi(value);
5620 /* no audio source uses val == 0 */
5621 if ((in->source != val) && (val != 0)) {
5622 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005623 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5624 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5625 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005626 (in->config.rate == 8000 || in->config.rate == 16000 ||
5627 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005628 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005629 err = voice_extn_compress_voip_open_input_stream(in);
5630 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005631 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005632 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005633 }
5634 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005635 }
5636 }
5637
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005638 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5639 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005640 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005641 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5642
5643 // Workaround: If routing to an non existing usb device, fail gracefully
5644 // The routing request will otherwise block during 10 second
5645 int card;
5646 if (audio_is_usb_in_device(val) &&
5647 (card = get_alive_usb_card(parms)) >= 0) {
5648
5649 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5650 ret = -ENOSYS;
5651 } else {
5652
5653 in->device = val;
5654 /* If recording is in progress, change the tx device to new device */
5655 if (!in->standby && !in->is_st_session) {
5656 ALOGV("update input routing change");
5657 // inform adm before actual routing to prevent glitches.
5658 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005659 adev->adm_on_routing_change(adev->adm_data,
5660 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005661 ret = select_devices(adev, in->usecase);
5662 }
5663 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005664 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005665 }
5666 }
5667
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305668 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5669 if (err >= 0) {
5670 strlcpy(in->profile, value, sizeof(in->profile));
5671 ALOGV("updating stream profile with value '%s'", in->profile);
5672 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5673 &adev->streams_input_cfg_list,
5674 in->device, in->flags, in->format,
5675 in->sample_rate, in->bit_width,
5676 in->profile, &in->app_type_cfg);
5677 }
5678
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005679 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005680 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005681
5682 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305683error:
Eric Laurent994a6932013-07-17 11:51:42 -07005684 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005685 return ret;
5686}
5687
5688static char* in_get_parameters(const struct audio_stream *stream,
5689 const char *keys)
5690{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005691 struct stream_in *in = (struct stream_in *)stream;
5692 struct str_parms *query = str_parms_create_str(keys);
5693 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005694 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005695
5696 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005697 if (reply) {
5698 str_parms_destroy(reply);
5699 }
5700 if (query) {
5701 str_parms_destroy(query);
5702 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005703 ALOGE("in_get_parameters: failed to create query or reply");
5704 return NULL;
5705 }
5706
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005707 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005708
5709 voice_extn_in_get_parameters(in, query, reply);
5710
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005711 stream_get_parameter_channels(query, reply,
5712 &in->supported_channel_masks[0]);
5713 stream_get_parameter_formats(query, reply,
5714 &in->supported_formats[0]);
5715 stream_get_parameter_rates(query, reply,
5716 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005717 str = str_parms_to_str(reply);
5718 str_parms_destroy(query);
5719 str_parms_destroy(reply);
5720
5721 ALOGV("%s: exit: returns - %s", __func__, str);
5722 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005723}
5724
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005725static int in_set_gain(struct audio_stream_in *stream __unused,
5726 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005727{
5728 return 0;
5729}
5730
5731static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5732 size_t bytes)
5733{
5734 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305735
5736 if (in == NULL) {
5737 ALOGE("%s: stream_in ptr is NULL", __func__);
5738 return -EINVAL;
5739 }
5740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005741 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305742 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305743 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005744
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005745 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305746
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005747 if (in->is_st_session) {
5748 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5749 /* Read from sound trigger HAL */
5750 audio_extn_sound_trigger_read(in, buffer, bytes);
5751 pthread_mutex_unlock(&in->lock);
5752 return bytes;
5753 }
5754
Haynes Mathew George16081042017-05-31 17:16:49 -07005755 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5756 ret = -ENOSYS;
5757 goto exit;
5758 }
5759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005760 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005761 pthread_mutex_lock(&adev->lock);
5762 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5763 ret = voice_extn_compress_voip_start_input_stream(in);
5764 else
5765 ret = start_input_stream(in);
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05305766
5767 if (ret == 0)
5768 amplifier_input_stream_start(stream);
5769
5770
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005771 pthread_mutex_unlock(&adev->lock);
5772 if (ret != 0) {
5773 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005774 }
5775 in->standby = 0;
5776 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005777
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005778 // what's the duration requested by the client?
5779 long ns = 0;
5780
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305781 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005782 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5783 in->config.rate;
5784
5785 request_in_focus(in, ns);
5786 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005787
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305788 if (audio_extn_cin_attached_usecase(in->usecase)) {
5789 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5790 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305791 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005792 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305793 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005794 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005795 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005796 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005797 } else if (audio_extn_ffv_get_stream() == in) {
5798 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305799 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005800 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305801 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5802 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5803 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5804 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305805 ret = -EINVAL;
5806 goto exit;
5807 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305808 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305809 ret = -errno;
5810 }
5811 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305812 /* bytes read is always set to bytes for non compress usecases */
5813 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005814 }
5815
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005816 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005818 /*
5819 * Instead of writing zeroes here, we could trust the hardware
5820 * to always provide zeroes when muted.
5821 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305822 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5823 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005824 memset(buffer, 0, bytes);
5825
5826exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005827 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305828 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005829 pthread_mutex_unlock(&in->lock);
5830
5831 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305832 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305833 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305834 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305835 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305836 in->standby = true;
5837 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305838 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5839 bytes_read = bytes;
5840 memset(buffer, 0, bytes);
5841 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005842 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005843 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305844 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305845 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005846 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305847 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005848}
5849
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005850static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005851{
5852 return 0;
5853}
5854
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005855static int add_remove_audio_effect(const struct audio_stream *stream,
5856 effect_handle_t effect,
5857 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005858{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005859 struct stream_in *in = (struct stream_in *)stream;
5860 int status = 0;
5861 effect_descriptor_t desc;
5862
5863 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005864 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5865
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005866 if (status != 0)
5867 return status;
5868
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005869 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005870 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08005871 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5872 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005873 in->enable_aec != enable &&
5874 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5875 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005876 if (!in->standby) {
5877 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5878 select_devices(in->dev, in->usecase);
5879 }
5880
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005881 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005882 if (in->enable_ns != enable &&
5883 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5884 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005885 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08005886 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5887 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005888 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5889 select_devices(in->dev, in->usecase);
5890 } else
5891 select_devices(in->dev, in->usecase);
5892 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005893 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005894 pthread_mutex_unlock(&in->dev->lock);
5895 pthread_mutex_unlock(&in->lock);
5896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005897 return 0;
5898}
5899
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005900static int in_add_audio_effect(const struct audio_stream *stream,
5901 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005902{
Eric Laurent994a6932013-07-17 11:51:42 -07005903 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005904 return add_remove_audio_effect(stream, effect, true);
5905}
5906
5907static int in_remove_audio_effect(const struct audio_stream *stream,
5908 effect_handle_t effect)
5909{
Eric Laurent994a6932013-07-17 11:51:42 -07005910 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005911 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005912}
5913
Haynes Mathew George16081042017-05-31 17:16:49 -07005914static int in_stop(const struct audio_stream_in* stream)
5915{
5916 struct stream_in *in = (struct stream_in *)stream;
5917 struct audio_device *adev = in->dev;
5918
5919 int ret = -ENOSYS;
5920 ALOGV("%s", __func__);
5921 pthread_mutex_lock(&adev->lock);
5922 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5923 in->capture_started && in->pcm != NULL) {
5924 pcm_stop(in->pcm);
5925 ret = stop_input_stream(in);
5926 in->capture_started = false;
5927 }
5928 pthread_mutex_unlock(&adev->lock);
5929 return ret;
5930}
5931
5932static int in_start(const struct audio_stream_in* stream)
5933{
5934 struct stream_in *in = (struct stream_in *)stream;
5935 struct audio_device *adev = in->dev;
5936 int ret = -ENOSYS;
5937
5938 ALOGV("%s in %p", __func__, in);
5939 pthread_mutex_lock(&adev->lock);
5940 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5941 !in->capture_started && in->pcm != NULL) {
5942 if (!in->capture_started) {
5943 ret = start_input_stream(in);
5944 if (ret == 0) {
5945 in->capture_started = true;
5946 }
5947 }
5948 }
5949 pthread_mutex_unlock(&adev->lock);
5950 return ret;
5951}
5952
5953static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5954 int32_t min_size_frames,
5955 struct audio_mmap_buffer_info *info)
5956{
5957 struct stream_in *in = (struct stream_in *)stream;
5958 struct audio_device *adev = in->dev;
5959 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005960 unsigned int offset1 = 0;
5961 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005962 const char *step = "";
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005963 uint32_t mmap_size = 0;
5964 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005965
5966 pthread_mutex_lock(&adev->lock);
5967 ALOGV("%s in %p", __func__, in);
5968
Sharad Sangle90e613f2018-05-04 16:15:38 +05305969 if (CARD_STATUS_OFFLINE == in->card_status||
5970 CARD_STATUS_OFFLINE == adev->card_status) {
5971 ALOGW("in->card_status or adev->card_status offline, try again");
5972 ret = -EIO;
5973 goto exit;
5974 }
5975
Haynes Mathew George16081042017-05-31 17:16:49 -07005976 if (info == NULL || min_size_frames == 0) {
5977 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5978 ret = -EINVAL;
5979 goto exit;
5980 }
5981 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5982 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5983 ALOGV("%s in %p", __func__, in);
5984 ret = -ENOSYS;
5985 goto exit;
5986 }
5987 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5988 if (in->pcm_device_id < 0) {
5989 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5990 __func__, in->pcm_device_id, in->usecase);
5991 ret = -EINVAL;
5992 goto exit;
5993 }
5994
5995 adjust_mmap_period_count(&in->config, min_size_frames);
5996
5997 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5998 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5999 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6000 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Sharad Sangle90e613f2018-05-04 16:15:38 +05306001 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
6002 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6003 in->card_status = CARD_STATUS_OFFLINE;
6004 adev->card_status = CARD_STATUS_OFFLINE;
6005 ret = -EIO;
6006 goto exit;
6007 }
6008
Haynes Mathew George16081042017-05-31 17:16:49 -07006009 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6010 step = "open";
6011 ret = -ENODEV;
6012 goto exit;
6013 }
6014
6015 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6016 if (ret < 0) {
6017 step = "begin";
6018 goto exit;
6019 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006020
Arun Mirpuriebe78a72018-10-04 18:23:46 -07006021 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
6022 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
6023 info->burst_size_frames = in->config.period_size;
6024 ret = platform_get_mmap_data_fd(adev->platform,
6025 in->pcm_device_id, 1 /*capture*/,
6026 &info->shared_memory_fd,
6027 &mmap_size);
6028 if (ret < 0) {
6029 // Fall back to non exclusive mode
6030 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6031 } else {
6032 if (mmap_size < buffer_size) {
6033 step = "mmap";
6034 goto exit;
6035 }
6036 // FIXME: indicate exclusive mode support by returning a negative buffer size
6037 info->buffer_size_frames *= -1;
6038 }
6039
6040 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006041
6042 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6043 if (ret < 0) {
6044 step = "commit";
6045 goto exit;
6046 }
6047
6048 in->standby = false;
6049 ret = 0;
6050
6051 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6052 __func__, info->shared_memory_address, info->buffer_size_frames);
6053
6054exit:
6055 if (ret != 0) {
6056 if (in->pcm == NULL) {
6057 ALOGE("%s: %s - %d", __func__, step, ret);
6058 } else {
6059 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6060 pcm_close(in->pcm);
6061 in->pcm = NULL;
6062 }
6063 }
6064 pthread_mutex_unlock(&adev->lock);
6065 return ret;
6066}
6067
6068static int in_get_mmap_position(const struct audio_stream_in *stream,
6069 struct audio_mmap_position *position)
6070{
6071 struct stream_in *in = (struct stream_in *)stream;
6072 ALOGVV("%s", __func__);
6073 if (position == NULL) {
6074 return -EINVAL;
6075 }
6076 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6077 return -ENOSYS;
6078 }
6079 if (in->pcm == NULL) {
6080 return -ENOSYS;
6081 }
6082 struct timespec ts = { 0, 0 };
6083 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6084 if (ret < 0) {
6085 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6086 return ret;
6087 }
Naresh Tannirua15d7e92018-11-02 09:49:44 +05306088 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07006089 return 0;
6090}
6091
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306092static int in_get_active_microphones(const struct audio_stream_in *stream,
6093 struct audio_microphone_characteristic_t *mic_array,
6094 size_t *mic_count) {
6095 struct stream_in *in = (struct stream_in *)stream;
6096 struct audio_device *adev = in->dev;
6097 ALOGVV("%s", __func__);
6098
6099 lock_input_stream(in);
6100 pthread_mutex_lock(&adev->lock);
6101 int ret = platform_get_active_microphones(adev->platform,
6102 audio_channel_count_from_in_mask(in->channel_mask),
6103 in->usecase, mic_array, mic_count);
6104 pthread_mutex_unlock(&adev->lock);
6105 pthread_mutex_unlock(&in->lock);
6106
6107 return ret;
6108}
6109
6110static int adev_get_microphones(const struct audio_hw_device *dev,
6111 struct audio_microphone_characteristic_t *mic_array,
6112 size_t *mic_count) {
6113 struct audio_device *adev = (struct audio_device *)dev;
6114 ALOGVV("%s", __func__);
6115
6116 pthread_mutex_lock(&adev->lock);
6117 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6118 pthread_mutex_unlock(&adev->lock);
6119
6120 return ret;
6121}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306122int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006123 audio_io_handle_t handle,
6124 audio_devices_t devices,
6125 audio_output_flags_t flags,
6126 struct audio_config *config,
6127 struct audio_stream_out **stream_out,
6128 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006129{
6130 struct audio_device *adev = (struct audio_device *)dev;
6131 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306132 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006133 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006134 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306135 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006136 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6137 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6138 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6139 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006140
kunleizdff872d2018-08-20 14:40:33 +08006141 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006142 is_usb_dev = false;
6143 devices = AUDIO_DEVICE_OUT_SPEAKER;
6144 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6145 __func__, devices);
6146 }
6147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006148 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306149
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006150 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6151
Mingming Yin3a941d42016-02-17 18:08:05 -08006152 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6153 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306154 devices, flags, &out->stream);
6155
6156
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006157 if (!out) {
6158 return -ENOMEM;
6159 }
6160
Haynes Mathew George204045b2015-02-25 20:32:03 -08006161 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006162 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306163 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006164 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006165 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6166
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006167 if (devices == AUDIO_DEVICE_NONE)
6168 devices = AUDIO_DEVICE_OUT_SPEAKER;
6169
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006170 out->flags = flags;
6171 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006172 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006173 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006174 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306175 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306176 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6177 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6178 else
6179 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006180 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006181 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006182 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306183 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306184 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306185 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006186 out->hal_output_suspend_supported = 0;
6187 out->dynamic_pm_qos_config_supported = 0;
Surendar Karka5a18a7a2018-04-26 11:28:38 +05306188 out->set_dual_mono = false;
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05306189 out->prev_card_status_offline = false;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05306190 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006191
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306192 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306193 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006194 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6195
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006196 if (audio_is_linear_pcm(out->format) &&
6197 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
6198 pthread_mutex_lock(&adev->lock);
6199 if (is_hdmi) {
6200 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6201 ret = read_hdmi_sink_caps(out);
6202 } else if (is_usb_dev) {
6203 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6204 &config->format,
6205 &out->supported_formats[0],
6206 MAX_SUPPORTED_FORMATS,
6207 &config->channel_mask,
6208 &out->supported_channel_masks[0],
6209 MAX_SUPPORTED_CHANNEL_MASKS,
6210 &config->sample_rate,
6211 &out->supported_sample_rates[0],
6212 MAX_SUPPORTED_SAMPLE_RATES);
6213 ALOGV("plugged dev USB ret %d", ret);
6214 } else {
6215 ret = -1;
6216 }
6217 pthread_mutex_unlock(&adev->lock);
6218 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006219 if (ret == -ENOSYS) {
6220 /* ignore and go with default */
6221 ret = 0;
6222 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006223 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006224 goto error_open;
6225 }
6226 }
6227 }
6228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006229 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07006230#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006231 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6232 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6233 out->sample_rate == 32000 || out->sample_rate == 48000)) {
6234 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
6235 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
6236 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
6237
6238 out->config = default_pcm_config_voip_copp;
6239 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6240 out->config.rate = out->sample_rate;
6241
6242#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05306243 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006244 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08006245 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006246 ret = voice_extn_compress_voip_open_output_stream(out);
6247 if (ret != 0) {
6248 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6249 __func__, ret);
6250 goto error_open;
6251 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006252#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006253 } else if (audio_is_linear_pcm(out->format) &&
6254 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6255 out->channel_mask = config->channel_mask;
6256 out->sample_rate = config->sample_rate;
6257 out->format = config->format;
6258 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6259 // does this change?
6260 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6261 out->config.rate = config->sample_rate;
6262 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6263 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6264 audio_bytes_per_sample(config->format));
6265 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006266 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306267 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306268 pthread_mutex_lock(&adev->lock);
6269 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6270 pthread_mutex_unlock(&adev->lock);
6271
6272 // reject offload during card offline to allow
6273 // fallback to s/w paths
6274 if (offline) {
6275 ret = -ENODEV;
6276 goto error_open;
6277 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006278
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006279 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6280 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6281 ALOGE("%s: Unsupported Offload information", __func__);
6282 ret = -EINVAL;
6283 goto error_open;
6284 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006285
Atul Khare3fa6e542017-08-09 00:56:17 +05306286 if (config->offload_info.format == 0)
6287 config->offload_info.format = config->format;
6288 if (config->offload_info.sample_rate == 0)
6289 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006290
Mingming Yin90310102013-11-13 16:57:00 -08006291 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306292 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006293 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006294 ret = -EINVAL;
6295 goto error_open;
6296 }
6297
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006298 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6299 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6300 (audio_extn_passthru_is_passthrough_stream(out)) &&
6301 !((config->sample_rate == 48000) ||
6302 (config->sample_rate == 96000) ||
6303 (config->sample_rate == 192000))) {
6304 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6305 __func__, config->sample_rate, config->offload_info.format);
6306 ret = -EINVAL;
6307 goto error_open;
6308 }
6309
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006310 out->compr_config.codec = (struct snd_codec *)
6311 calloc(1, sizeof(struct snd_codec));
6312
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006313 if (!out->compr_config.codec) {
6314 ret = -ENOMEM;
6315 goto error_open;
6316 }
6317
Dhananjay Kumarac341582017-02-23 23:42:25 +05306318 out->stream.pause = out_pause;
6319 out->stream.resume = out_resume;
6320 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306321 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306322 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006323 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306324 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006325 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306326 } else {
6327 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6328 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006329 }
vivek mehta446c3962015-09-14 10:57:35 -07006330
6331 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006332 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6333 config->format == 0 && config->sample_rate == 0 &&
6334 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006335 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006336 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6337 } else {
6338 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6339 ret = -EEXIST;
6340 goto error_open;
6341 }
vivek mehta446c3962015-09-14 10:57:35 -07006342 }
6343
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006344 if (config->offload_info.channel_mask)
6345 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006346 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006347 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006348 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006349 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306350 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006351 ret = -EINVAL;
6352 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006353 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006354
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006355 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006356 out->sample_rate = config->offload_info.sample_rate;
6357
Mingming Yin3ee55c62014-08-04 14:23:35 -07006358 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006359
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306360 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306361 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306362 audio_extn_dolby_send_ddp_endp_params(adev);
6363 audio_extn_dolby_set_dmid(adev);
6364 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006365
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006366 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006367 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006368 out->compr_config.codec->bit_rate =
6369 config->offload_info.bit_rate;
6370 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306371 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006372 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306373 /* Update bit width only for non passthrough usecases.
6374 * For passthrough usecases, the output will always be opened @16 bit
6375 */
6376 if (!audio_extn_passthru_is_passthrough_stream(out))
6377 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306378
6379 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6380 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6381 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6382
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006383 /*TODO: Do we need to change it for passthrough */
6384 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006385
Manish Dewangana6fc5442015-08-24 20:30:31 +05306386 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6387 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306388 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306389 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306390 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6391 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306392
6393 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6394 AUDIO_FORMAT_PCM) {
6395
6396 /*Based on platform support, configure appropriate alsa format for corresponding
6397 *hal input format.
6398 */
6399 out->compr_config.codec->format = hal_format_to_alsa(
6400 config->offload_info.format);
6401
Ashish Jain83a6cc22016-06-28 14:34:17 +05306402 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306403 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306404 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306405
Dhananjay Kumarac341582017-02-23 23:42:25 +05306406 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306407 *hal input format and alsa format might differ based on platform support.
6408 */
6409 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306410 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306411
6412 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6413
6414 /* Check if alsa session is configured with the same format as HAL input format,
6415 * if not then derive correct fragment size needed to accomodate the
6416 * conversion of HAL input format to alsa format.
6417 */
6418 audio_extn_utils_update_direct_pcm_fragment_size(out);
6419
6420 /*if hal input and output fragment size is different this indicates HAL input format is
6421 *not same as the alsa format
6422 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306423 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306424 /*Allocate a buffer to convert input data to the alsa configured format.
6425 *size of convert buffer is equal to the size required to hold one fragment size
6426 *worth of pcm data, this is because flinger does not write more than fragment_size
6427 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306428 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6429 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306430 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6431 ret = -ENOMEM;
6432 goto error_open;
6433 }
6434 }
6435 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6436 out->compr_config.fragment_size =
6437 audio_extn_passthru_get_buffer_size(&config->offload_info);
6438 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6439 } else {
6440 out->compr_config.fragment_size =
6441 platform_get_compress_offload_buffer_size(&config->offload_info);
6442 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6443 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006444
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306445 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6446 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6447 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006448 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306449 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006450
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306451 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6452 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6453 }
6454
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006455 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6456 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006457
Manish Dewangan69426c82017-01-30 17:35:36 +05306458 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6459 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6460 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6461 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6462 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6463 } else {
6464 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6465 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006466
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306467 memset(&out->channel_map_param, 0,
6468 sizeof(struct audio_out_channel_map_param));
6469
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006470 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306471 out->send_next_track_params = false;
6472 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006473 out->offload_state = OFFLOAD_STATE_IDLE;
6474 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006475 out->writeAt.tv_sec = 0;
6476 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006477
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006478 audio_extn_dts_create_state_notifier_node(out->usecase);
6479
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006480 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6481 __func__, config->offload_info.version,
6482 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306483
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306484 /* Check if DSD audio format is supported in codec
6485 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306486 */
6487
6488 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306489 (!platform_check_codec_dsd_support(adev->platform) ||
6490 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306491 ret = -EINVAL;
6492 goto error_open;
6493 }
6494
Ashish Jain5106d362016-05-11 19:23:33 +05306495 /* Disable gapless if any of the following is true
6496 * passthrough playback
6497 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306498 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306499 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306500 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306501 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006502 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306503 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306504 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306505 check_and_set_gapless_mode(adev, false);
6506 } else
6507 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006508
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306509 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006510 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6511 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306512 if (config->format == AUDIO_FORMAT_DSD) {
6513 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6514 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6515 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006516
6517 create_offload_callback_thread(out);
6518
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006519 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006520 switch (config->sample_rate) {
6521 case 0:
6522 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6523 break;
6524 case 8000:
6525 case 16000:
6526 case 48000:
6527 out->sample_rate = config->sample_rate;
6528 break;
6529 default:
6530 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
6531 config->sample_rate);
6532 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6533 ret = -EINVAL;
6534 goto error_open;
6535 }
6536 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6537 switch (config->channel_mask) {
6538 case AUDIO_CHANNEL_NONE:
6539 case AUDIO_CHANNEL_OUT_STEREO:
6540 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6541 break;
6542 default:
6543 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
6544 config->channel_mask);
6545 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6546 ret = -EINVAL;
6547 goto error_open;
6548 }
6549 switch (config->format) {
6550 case AUDIO_FORMAT_DEFAULT:
6551 case AUDIO_FORMAT_PCM_16_BIT:
6552 out->format = AUDIO_FORMAT_PCM_16_BIT;
6553 break;
6554 default:
6555 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
6556 config->format);
6557 config->format = AUDIO_FORMAT_PCM_16_BIT;
6558 ret = -EINVAL;
6559 goto error_open;
6560 }
6561
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306562 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006563 if (ret != 0) {
6564 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006565 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006566 goto error_open;
6567 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006568 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006569 if (config->sample_rate == 0)
6570 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6571 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6572 config->sample_rate != 8000) {
6573 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6574 ret = -EINVAL;
6575 goto error_open;
6576 }
6577 out->sample_rate = config->sample_rate;
6578 out->config.rate = config->sample_rate;
6579 if (config->format == AUDIO_FORMAT_DEFAULT)
6580 config->format = AUDIO_FORMAT_PCM_16_BIT;
6581 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6582 config->format = AUDIO_FORMAT_PCM_16_BIT;
6583 ret = -EINVAL;
6584 goto error_open;
6585 }
6586 out->format = config->format;
6587 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
6588 out->config = pcm_config_afe_proxy_playback;
6589 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006590 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05306591 unsigned int channels = 0;
6592 /*Update config params to default if not set by the caller*/
6593 if (config->sample_rate == 0)
6594 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6595 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6596 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6597 if (config->format == AUDIO_FORMAT_DEFAULT)
6598 config->format = AUDIO_FORMAT_PCM_16_BIT;
6599
6600 channels = audio_channel_count_from_out_mask(out->channel_mask);
6601
Varun Balaraje49253e2017-07-06 19:48:56 +05306602 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6603 out->usecase = get_interactive_usecase(adev);
6604 out->config = pcm_config_low_latency;
6605 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306606 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006607 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6608 out->flags);
6609 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006610 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6611 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6612 out->config = pcm_config_mmap_playback;
6613 out->stream.start = out_start;
6614 out->stream.stop = out_stop;
6615 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6616 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306617 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6618 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006619 out->hal_output_suspend_supported =
6620 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6621 out->dynamic_pm_qos_config_supported =
6622 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6623 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006624 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6625 } else {
6626 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6627 //the mixer path will be a string similar to "low-latency-playback resume"
6628 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6629 strlcat(out->pm_qos_mixer_path,
6630 " resume", MAX_MIXER_PATH_LEN);
6631 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6632 out->pm_qos_mixer_path);
6633 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306634 out->config = pcm_config_low_latency;
6635 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6636 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6637 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306638 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6639 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6640 if (out->config.period_size <= 0) {
6641 ALOGE("Invalid configuration period size is not valid");
6642 ret = -EINVAL;
6643 goto error_open;
6644 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306645 } else {
6646 /* primary path is the default path selected if no other outputs are available/suitable */
6647 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6648 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6649 }
6650 out->hal_ip_format = format = out->format;
6651 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6652 out->hal_op_format = pcm_format_to_hal(out->config.format);
6653 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6654 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006655 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306656 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306657 if (out->hal_ip_format != out->hal_op_format) {
6658 uint32_t buffer_size = out->config.period_size *
6659 format_to_bitwidth_table[out->hal_op_format] *
6660 out->config.channels;
6661 out->convert_buffer = calloc(1, buffer_size);
6662 if (out->convert_buffer == NULL){
6663 ALOGE("Allocation failed for convert buffer for size %d",
6664 out->compr_config.fragment_size);
6665 ret = -ENOMEM;
6666 goto error_open;
6667 }
6668 ALOGD("Convert buffer allocated of size %d", buffer_size);
6669 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006670 }
6671
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006672 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6673 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306674
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006675 /* TODO remove this hardcoding and check why width is zero*/
6676 if (out->bit_width == 0)
6677 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306678 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006679 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006680 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306681 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306682 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006683 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6684 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6685 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006686 if(adev->primary_output == NULL)
6687 adev->primary_output = out;
6688 else {
6689 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006690 ret = -EEXIST;
6691 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006692 }
6693 }
6694
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006695 /* Check if this usecase is already existing */
6696 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006697 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6698 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006699 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006700 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006701 ret = -EEXIST;
6702 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006703 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006705 pthread_mutex_unlock(&adev->lock);
6706
6707 out->stream.common.get_sample_rate = out_get_sample_rate;
6708 out->stream.common.set_sample_rate = out_set_sample_rate;
6709 out->stream.common.get_buffer_size = out_get_buffer_size;
6710 out->stream.common.get_channels = out_get_channels;
6711 out->stream.common.get_format = out_get_format;
6712 out->stream.common.set_format = out_set_format;
6713 out->stream.common.standby = out_standby;
6714 out->stream.common.dump = out_dump;
6715 out->stream.common.set_parameters = out_set_parameters;
6716 out->stream.common.get_parameters = out_get_parameters;
6717 out->stream.common.add_audio_effect = out_add_audio_effect;
6718 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6719 out->stream.get_latency = out_get_latency;
6720 out->stream.set_volume = out_set_volume;
6721 out->stream.write = out_write;
6722 out->stream.get_render_position = out_get_render_position;
6723 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006724 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006725
Haynes Mathew George16081042017-05-31 17:16:49 -07006726 if (out->realtime)
6727 out->af_period_multiplier = af_period_multiplier;
6728 else
6729 out->af_period_multiplier = 1;
6730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006731 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006732 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006733 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006734
6735 config->format = out->stream.common.get_format(&out->stream.common);
6736 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6737 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05306738 register_format(out->format, out->supported_formats);
6739 register_channel_mask(out->channel_mask, out->supported_channel_masks);
6740 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006741
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306742 /*
6743 By locking output stream before registering, we allow the callback
6744 to update stream's state only after stream's initial state is set to
6745 adev state.
6746 */
6747 lock_output_stream(out);
6748 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6749 pthread_mutex_lock(&adev->lock);
6750 out->card_status = adev->card_status;
6751 pthread_mutex_unlock(&adev->lock);
6752 pthread_mutex_unlock(&out->lock);
6753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006754 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306755 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006756 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006757
6758 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6759 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6760 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006761 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306762 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006763 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006764 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306765 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006766 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6767 out->usecase, PCM_PLAYBACK);
6768 hdlr_stream_cfg.flags = out->flags;
6769 hdlr_stream_cfg.type = PCM_PLAYBACK;
6770 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6771 &hdlr_stream_cfg);
6772 if (ret) {
6773 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6774 out->adsp_hdlr_stream_handle = NULL;
6775 }
6776 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306777 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006778 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006779 if (ret < 0) {
6780 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6781 out->ip_hdlr_handle = NULL;
6782 }
6783 }
Eric Laurent994a6932013-07-17 11:51:42 -07006784 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006785 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006786
6787error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306788 if (out->convert_buffer)
6789 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006790 free(out);
6791 *stream_out = NULL;
6792 ALOGD("%s: exit: ret %d", __func__, ret);
6793 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006794}
6795
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306796void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006797 struct audio_stream_out *stream)
6798{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006799 struct stream_out *out = (struct stream_out *)stream;
6800 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006801 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006802
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006803 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306804
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306805 // must deregister from sndmonitor first to prevent races
6806 // between the callback and close_stream
6807 audio_extn_snd_mon_unregister_listener(out);
6808
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006809 /* close adsp hdrl session before standby */
6810 if (out->adsp_hdlr_stream_handle) {
6811 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6812 if (ret)
6813 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6814 out->adsp_hdlr_stream_handle = NULL;
6815 }
6816
Manish Dewangan21a850a2017-08-14 12:03:55 +05306817 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006818 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6819 out->ip_hdlr_handle = NULL;
6820 }
6821
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006822 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306823 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006824 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306825 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306826 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006827 if(ret != 0)
6828 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6829 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006830 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006831 out_standby(&stream->common);
6832
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006833 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006834 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006835 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006836 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006837 if (out->compr_config.codec != NULL)
6838 free(out->compr_config.codec);
6839 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006840
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306841 out->a2dp_compress_mute = false;
6842
Varun Balaraje49253e2017-07-06 19:48:56 +05306843 if (is_interactive_usecase(out->usecase))
6844 free_interactive_usecase(adev, out->usecase);
6845
Ashish Jain83a6cc22016-06-28 14:34:17 +05306846 if (out->convert_buffer != NULL) {
6847 free(out->convert_buffer);
6848 out->convert_buffer = NULL;
6849 }
6850
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006851 if (adev->voice_tx_output == out)
6852 adev->voice_tx_output = NULL;
6853
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306854 if (adev->primary_output == out)
6855 adev->primary_output = NULL;
6856
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006857 pthread_cond_destroy(&out->cond);
6858 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006859 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006860 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006861}
6862
6863static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6864{
6865 struct audio_device *adev = (struct audio_device *)dev;
6866 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006867 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006868 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006869 int ret;
6870 int status = 0;
Zhou Songa32012a2019-05-21 18:08:51 +08006871 struct listnode *node;
6872 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006873
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006874 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006875 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006876
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306877 if (!parms)
6878 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306879
Zhou Songa32012a2019-05-21 18:08:51 +08006880 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306881 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6882 if (ret >= 0) {
6883 /* When set to false, HAL should disable EC and NS */
Zhou Songa32012a2019-05-21 18:08:51 +08006884 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306885 adev->bt_sco_on = true;
Zhou Songa32012a2019-05-21 18:08:51 +08006886 } else {
6887 ALOGD("route device to handset/mic when sco is off");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306888 adev->bt_sco_on = false;
Zhou Songa32012a2019-05-21 18:08:51 +08006889 list_for_each(node, &adev->usecase_list) {
6890 usecase = node_to_item(node, struct audio_usecase, list);
6891 if ((usecase->type == PCM_PLAYBACK) && usecase->stream.out &&
6892 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_SCO))
6893 usecase->stream.out->devices = AUDIO_DEVICE_OUT_EARPIECE;
6894 else if ((usecase->type == PCM_CAPTURE) && usecase->stream.in &&
6895 (usecase->stream.in->device & AUDIO_DEVICE_IN_ALL_SCO))
6896 usecase->stream.in->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
6897 else
6898 continue;
6899 select_devices(adev, usecase->id);
6900 }
6901 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306902 }
6903
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006904 status = voice_set_parameters(adev, parms);
6905 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006906 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006907
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006908 status = platform_set_parameters(adev->platform, parms);
6909 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006910 goto done;
6911
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006912 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6913 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006914 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006915 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6916 adev->bluetooth_nrec = true;
6917 else
6918 adev->bluetooth_nrec = false;
6919 }
6920
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006921 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6922 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006923 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6924 adev->screen_off = false;
6925 else
6926 adev->screen_off = true;
6927 }
6928
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006929 ret = str_parms_get_int(parms, "rotation", &val);
6930 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006931 bool reverse_speakers = false;
6932 switch(val) {
6933 // FIXME: note that the code below assumes that the speakers are in the correct placement
6934 // relative to the user when the device is rotated 90deg from its default rotation. This
6935 // assumption is device-specific, not platform-specific like this code.
6936 case 270:
6937 reverse_speakers = true;
6938 break;
6939 case 0:
6940 case 90:
6941 case 180:
6942 break;
6943 default:
6944 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006945 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006946 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006947 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006948 // check and set swap
6949 // - check if orientation changed and speaker active
6950 // - set rotation and cache the rotation value
6951 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006952 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006953 }
6954
Mingming Yin514a8bc2014-07-29 15:22:21 -07006955 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6956 if (ret >= 0) {
6957 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6958 adev->bt_wb_speech_enabled = true;
6959 else
6960 adev->bt_wb_speech_enabled = false;
6961 }
6962
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006963 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6964 if (ret >= 0) {
6965 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306966 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08006967 if (audio_is_output_device(val) &&
6968 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006969 ALOGV("cache new ext disp type and edid");
6970 ret = platform_get_ext_disp_type(adev->platform);
6971 if (ret < 0) {
6972 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05306973 } else {
6974 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006975 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306976 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07006977 /*
6978 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6979 * Per AudioPolicyManager, USB device is higher priority than WFD.
6980 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6981 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6982 * starting voice call on USB
6983 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006984 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306985 if (ret >= 0)
6986 audio_extn_usb_add_device(device, atoi(value));
6987
Zhou Song6f862822017-11-06 17:27:57 +08006988 if (!audio_extn_usb_is_tunnel_supported()) {
6989 ALOGV("detected USB connect .. disable proxy");
6990 adev->allow_afe_proxy_usage = false;
6991 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006992 }
6993 }
6994
6995 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6996 if (ret >= 0) {
6997 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306998 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07006999 /*
7000 * The HDMI / Displayport disconnect handling has been moved to
7001 * audio extension to ensure that its parameters are not
7002 * invalidated prior to updating sysfs of the disconnect event
7003 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
7004 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307005 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007006 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307007 if (ret >= 0)
7008 audio_extn_usb_remove_device(device, atoi(value));
7009
Zhou Song6f862822017-11-06 17:27:57 +08007010 if (!audio_extn_usb_is_tunnel_supported()) {
7011 ALOGV("detected USB disconnect .. enable proxy");
7012 adev->allow_afe_proxy_usage = true;
7013 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007014 }
7015 }
7016
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307017 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
7018 if (ret >= 0) {
7019 struct audio_usecase *usecase;
7020 struct listnode *node;
7021 list_for_each(node, &adev->usecase_list) {
7022 usecase = node_to_item(node, struct audio_usecase, list);
7023 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07007024 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307025 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08007026
7027 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307028 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08007029 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307030 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307031 //force device switch to re configure encoder
7032 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307033 audio_extn_a2dp_set_handoff_mode(false);
7034 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307035 break;
7036 }
7037 }
7038 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007039
7040 //handle vr audio setparam
7041 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7042 value, sizeof(value));
7043 if (ret >= 0) {
7044 ALOGI("Setting vr mode to be %s", value);
7045 if (!strncmp(value, "true", 4)) {
7046 adev->vr_audio_mode_enabled = true;
7047 ALOGI("Setting vr mode to true");
7048 } else if (!strncmp(value, "false", 5)) {
7049 adev->vr_audio_mode_enabled = false;
7050 ALOGI("Setting vr mode to false");
7051 } else {
7052 ALOGI("wrong vr mode set");
7053 }
7054 }
7055
Balázs Triszka6e101332018-02-26 22:11:10 +01007056 ret = str_parms_get_int(parms, "ultrasound_enable", &val);
7057 if (ret >= 0) {
7058 if (val == 1) {
7059 us_start();
7060 } else {
7061 us_stop();
7062 }
7063 }
7064
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05307065 amplifier_set_parameters(parms);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307066 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007067done:
7068 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007069 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307070error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007071 ALOGV("%s: exit with code(%d)", __func__, status);
7072 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007073}
7074
7075static char* adev_get_parameters(const struct audio_hw_device *dev,
7076 const char *keys)
7077{
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05307078 ALOGD("%s:%s", __func__, keys);
7079
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007080 struct audio_device *adev = (struct audio_device *)dev;
7081 struct str_parms *reply = str_parms_create();
7082 struct str_parms *query = str_parms_create_str(keys);
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05307083
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007084 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05307085 char value[256] = {0};
7086 int ret = 0;
7087
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007088 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007089 if (reply) {
7090 str_parms_destroy(reply);
7091 }
7092 if (query) {
7093 str_parms_destroy(query);
7094 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007095 ALOGE("adev_get_parameters: failed to create query or reply");
7096 return NULL;
7097 }
7098
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007099 //handle vr audio getparam
7100
7101 ret = str_parms_get_str(query,
7102 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7103 value, sizeof(value));
7104
7105 if (ret >= 0) {
7106 bool vr_audio_enabled = false;
7107 pthread_mutex_lock(&adev->lock);
7108 vr_audio_enabled = adev->vr_audio_mode_enabled;
7109 pthread_mutex_unlock(&adev->lock);
7110
7111 ALOGI("getting vr mode to %d", vr_audio_enabled);
7112
7113 if (vr_audio_enabled) {
7114 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7115 "true");
7116 goto exit;
7117 } else {
7118 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7119 "false");
7120 goto exit;
7121 }
7122 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007123
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007124 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007125 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08007126 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007127 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05307128 pthread_mutex_unlock(&adev->lock);
7129
Naresh Tannirud7205b62014-06-20 02:54:48 +05307130exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007131 str = str_parms_to_str(reply);
7132 str_parms_destroy(query);
7133 str_parms_destroy(reply);
7134
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05307135 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007136 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007137}
7138
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007139static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007140{
7141 return 0;
7142}
7143
7144static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
7145{
Haynes Mathew George5191a852013-09-11 14:19:36 -07007146 int ret;
7147 struct audio_device *adev = (struct audio_device *)dev;
7148 pthread_mutex_lock(&adev->lock);
7149 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07007150 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07007151 pthread_mutex_unlock(&adev->lock);
7152 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007153}
7154
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007155static int adev_set_master_volume(struct audio_hw_device *dev __unused,
7156 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007157{
7158 return -ENOSYS;
7159}
7160
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007161static int adev_get_master_volume(struct audio_hw_device *dev __unused,
7162 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007163{
7164 return -ENOSYS;
7165}
7166
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007167static int adev_set_master_mute(struct audio_hw_device *dev __unused,
7168 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007169{
7170 return -ENOSYS;
7171}
7172
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007173static int adev_get_master_mute(struct audio_hw_device *dev __unused,
7174 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007175{
7176 return -ENOSYS;
7177}
7178
7179static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
7180{
7181 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07007182 struct listnode *node;
7183 struct audio_usecase *usecase = NULL;
7184 int ret = 0;
kunleiz60c17e72017-05-04 12:15:35 +08007185
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007186 pthread_mutex_lock(&adev->lock);
7187 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007188 ALOGD("%s: mode %d\n", __func__, mode);
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05307189 if (amplifier_set_mode(mode) != 0)
7190 ALOGE("Failed setting amplifier mode");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007191 adev->mode = mode;
Kunlei Zhang0eab0432019-05-21 14:25:57 +08007192 if (voice_is_in_call(adev) &&
7193 (mode == AUDIO_MODE_NORMAL ||
7194 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07007195 list_for_each(node, &adev->usecase_list) {
7196 usecase = node_to_item(node, struct audio_usecase, list);
7197 if (usecase->type == VOICE_CALL)
7198 break;
7199 }
7200 if (usecase &&
7201 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
7202 ret = audio_extn_usb_check_and_set_svc_int(usecase,
7203 true);
7204 if (ret != 0) {
7205 /* default service interval was successfully updated,
7206 reopen USB backend with new service interval */
7207 check_usecases_codec_backend(adev,
7208 usecase,
7209 usecase->out_snd_device);
7210 }
7211 }
7212
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007213 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07007214 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007215 adev->current_call_output = NULL;
kunleiz60c17e72017-05-04 12:15:35 +08007216 // restore device for other active usecases after stop call
7217 list_for_each(node, &adev->usecase_list) {
7218 usecase = node_to_item(node, struct audio_usecase, list);
7219 select_devices(adev, usecase->id);
7220 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007221 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007222 }
7223 pthread_mutex_unlock(&adev->lock);
7224 return 0;
7225}
7226
7227static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
7228{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007229 int ret;
7230
7231 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08007232 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007233 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Derek Chencdd17c72014-11-24 12:39:14 -08007234 if (adev->ext_hw_plugin)
7235 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007236 pthread_mutex_unlock(&adev->lock);
7237
7238 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007239}
7240
7241static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
7242{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007243 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007244 return 0;
7245}
7246
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007247static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007248 const struct audio_config *config)
7249{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007250 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007251
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007252 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
7253 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007254}
7255
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007256static bool adev_input_allow_hifi_record(struct audio_device *adev,
7257 audio_devices_t devices,
7258 audio_input_flags_t flags,
7259 audio_source_t source) {
7260 const bool allowed = true;
7261
7262 if (!audio_is_usb_in_device(devices))
7263 return !allowed;
7264
7265 switch (flags) {
7266 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007267 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07007268 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7269 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007270 default:
7271 return !allowed;
7272 }
7273
7274 switch (source) {
7275 case AUDIO_SOURCE_DEFAULT:
7276 case AUDIO_SOURCE_MIC:
7277 case AUDIO_SOURCE_UNPROCESSED:
7278 break;
7279 default:
7280 return !allowed;
7281 }
7282
7283 switch (adev->mode) {
7284 case 0:
7285 break;
7286 default:
7287 return !allowed;
7288 }
7289
7290 return allowed;
7291}
7292
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007293static int adev_update_voice_comm_input_stream(struct stream_in *in,
7294 struct audio_config *config)
7295{
7296 bool valid_rate = (config->sample_rate == 8000 ||
7297 config->sample_rate == 16000 ||
7298 config->sample_rate == 32000 ||
7299 config->sample_rate == 48000);
7300 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
7301
7302#ifndef COMPRESS_VOIP_ENABLED
kunleizd96526c2018-04-09 11:12:32 +08007303 if (valid_rate && valid_ch &&
7304 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007305 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7306 in->config = default_pcm_config_voip_copp;
7307 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
7308 DEFAULT_VOIP_BUF_DURATION_MS,
7309 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
7310 } else {
kunleizbdd9ad02018-04-24 10:53:17 +08007311 ALOGW("%s No valid input in voip, use defaults"
7312 "sample rate %u, channel mask 0x%X",
7313 __func__, config->sample_rate, in->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007314 }
7315 in->config.rate = config->sample_rate;
7316 in->sample_rate = config->sample_rate;
7317#else
7318 //XXX needed for voice_extn_compress_voip_open_input_stream
7319 in->config.rate = config->sample_rate;
7320 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7321 voice_extn_compress_voip_is_active(in->dev)) &&
7322 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7323 valid_rate && valid_ch) {
7324 voice_extn_compress_voip_open_input_stream(in);
7325 // update rate entries to match config from AF
7326 in->config.rate = config->sample_rate;
7327 in->sample_rate = config->sample_rate;
7328 } else {
7329 ALOGW("%s compress voip not active, use defaults", __func__);
7330 }
7331#endif
7332 return 0;
7333}
7334
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007335static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007336 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007337 audio_devices_t devices,
7338 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007339 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307340 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007341 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007342 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007343{
7344 struct audio_device *adev = (struct audio_device *)dev;
7345 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007346 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007347 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007348 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05307349 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007350 bool is_usb_dev = audio_is_usb_in_device(devices);
7351 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
7352 devices,
7353 flags,
7354 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307355
kunleizdff872d2018-08-20 14:40:33 +08007356 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007357 is_usb_dev = false;
7358 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
7359 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
7360 __func__, devices);
7361 }
7362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007363 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007364
7365 if (!(is_usb_dev && may_use_hifi_record)) {
7366 if (config->sample_rate == 0)
7367 config->sample_rate = 48000;
7368 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7369 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7370 if (config->format == AUDIO_FORMAT_DEFAULT)
7371 config->format = AUDIO_FORMAT_PCM_16_BIT;
7372
7373 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
7374
7375 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
7376 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05307377 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007378
7379 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007380
7381 if (!in) {
7382 ALOGE("failed to allocate input stream");
7383 return -ENOMEM;
7384 }
7385
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307386 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307387 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7388 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007389 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007390 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007392 in->stream.common.get_sample_rate = in_get_sample_rate;
7393 in->stream.common.set_sample_rate = in_set_sample_rate;
7394 in->stream.common.get_buffer_size = in_get_buffer_size;
7395 in->stream.common.get_channels = in_get_channels;
7396 in->stream.common.get_format = in_get_format;
7397 in->stream.common.set_format = in_set_format;
7398 in->stream.common.standby = in_standby;
7399 in->stream.common.dump = in_dump;
7400 in->stream.common.set_parameters = in_set_parameters;
7401 in->stream.common.get_parameters = in_get_parameters;
7402 in->stream.common.add_audio_effect = in_add_audio_effect;
7403 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7404 in->stream.set_gain = in_set_gain;
7405 in->stream.read = in_read;
7406 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307407 in->stream.get_active_microphones = in_get_active_microphones;
Ramjee Singhacef98f2019-06-28 11:01:25 +05307408#if ANDROID_PLATFORM_SDK_VERSION >= 29
7409 in->stream.set_microphone_direction = in_set_microphone_direction;
7410 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
7411#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007412
7413 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007414 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007415 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007416 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007417 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007418 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007419 in->bit_width = 16;
7420 in->af_period_multiplier = 1;
7421
7422 /* Update config params with the requested sample rate and channels */
7423 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
7424 (adev->mode != AUDIO_MODE_IN_CALL)) {
7425 ret = -EINVAL;
7426 goto err_open;
7427 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007428
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007429 if (is_usb_dev && may_use_hifi_record) {
7430 /* HiFi record selects an appropriate format, channel, rate combo
7431 depending on sink capabilities*/
7432 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7433 &config->format,
7434 &in->supported_formats[0],
7435 MAX_SUPPORTED_FORMATS,
7436 &config->channel_mask,
7437 &in->supported_channel_masks[0],
7438 MAX_SUPPORTED_CHANNEL_MASKS,
7439 &config->sample_rate,
7440 &in->supported_sample_rates[0],
7441 MAX_SUPPORTED_SAMPLE_RATES);
7442 if (ret != 0) {
7443 ret = -EINVAL;
7444 goto err_open;
7445 }
7446 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007447 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307448 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05307449 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
7450 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
7451 in->config.format = PCM_FORMAT_S32_LE;
7452 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307453 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
7454 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
7455 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
7456 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7457 bool ret_error = false;
7458 in->bit_width = 24;
7459 /* 24 bit is restricted to UNPROCESSED source only,also format supported
7460 from HAL is 24_packed and 8_24
7461 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
7462 24_packed return error indicating supported format is 24_packed
7463 *> In case of any other source requesting 24 bit or float return error
7464 indicating format supported is 16 bit only.
7465
7466 on error flinger will retry with supported format passed
7467 */
7468 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
7469 (source != AUDIO_SOURCE_CAMCORDER)) {
7470 config->format = AUDIO_FORMAT_PCM_16_BIT;
7471 if (config->sample_rate > 48000)
7472 config->sample_rate = 48000;
7473 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07007474 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
7475 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307476 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
7477 ret_error = true;
7478 }
7479
7480 if (ret_error) {
7481 ret = -EINVAL;
7482 goto err_open;
7483 }
7484 }
7485
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007486 in->channel_mask = config->channel_mask;
7487 in->format = config->format;
7488
7489 in->usecase = USECASE_AUDIO_RECORD;
7490 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
7491 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
7492 is_low_latency = true;
7493#if LOW_LATENCY_CAPTURE_USE_CASE
7494 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
7495#endif
7496 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
7497 }
7498
7499 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
7500 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
7501 in->realtime = 0;
7502 in->usecase = USECASE_AUDIO_RECORD_MMAP;
7503 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07007504 in->config.format = pcm_format_from_audio_format(config->format);
Weiyin Jiangde7925e2018-11-27 18:45:53 +08007505 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007506 in->stream.start = in_start;
7507 in->stream.stop = in_stop;
7508 in->stream.create_mmap_buffer = in_create_mmap_buffer;
7509 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007510 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007511 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
7512 } else if (in->realtime) {
7513 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07007514 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007515 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007516 in->sample_rate = in->config.rate;
7517 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07007518 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007519 in->usecase = USECASE_AUDIO_RECORD_HIFI;
7520 in->config = pcm_config_audio_capture;
7521 frame_size = audio_stream_in_frame_size(&in->stream);
7522 buffer_size = get_input_buffer_size(config->sample_rate,
7523 config->format,
7524 channel_count,
7525 false /*is_low_latency*/);
7526 in->config.period_size = buffer_size / frame_size;
7527 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007528 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07007529 switch (config->format) {
7530 case AUDIO_FORMAT_PCM_32_BIT:
7531 in->bit_width = 32;
7532 break;
7533 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
7534 case AUDIO_FORMAT_PCM_8_24_BIT:
7535 in->bit_width = 24;
7536 break;
7537 default:
7538 in->bit_width = 16;
7539 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007540 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007541 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007542 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05307543 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007544 if (config->sample_rate == 0)
7545 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7546 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
7547 config->sample_rate != 8000) {
7548 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7549 ret = -EINVAL;
7550 goto err_open;
7551 }
7552 if (config->format == AUDIO_FORMAT_DEFAULT)
7553 config->format = AUDIO_FORMAT_PCM_16_BIT;
7554 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
7555 config->format = AUDIO_FORMAT_PCM_16_BIT;
7556 ret = -EINVAL;
7557 goto err_open;
7558 }
7559
7560 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
7561 in->config = pcm_config_afe_proxy_record;
7562 in->config.channels = channel_count;
7563 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307564 in->sample_rate = config->sample_rate;
Haynes Mathew George46740472017-10-27 18:40:12 -07007565 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05307566 int ret_val;
7567 pthread_mutex_lock(&adev->lock);
7568 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
7569 in, config, &channel_mask_updated);
7570 pthread_mutex_unlock(&adev->lock);
7571
7572 if (!ret_val) {
7573 if (channel_mask_updated == true) {
7574 ALOGD("%s: return error to retry with updated channel mask (%#x)",
7575 __func__, config->channel_mask);
7576 ret = -EINVAL;
7577 goto err_open;
7578 }
7579 ALOGD("%s: created multi-channel session succesfully",__func__);
7580 } else if (audio_extn_compr_cap_enabled() &&
7581 audio_extn_compr_cap_format_supported(config->format) &&
7582 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
7583 audio_extn_compr_cap_init(in);
7584 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05307585 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05307586 ret = audio_extn_cin_configure_input_stream(in);
7587 if (ret)
7588 goto err_open;
7589 } else {
7590 in->config = pcm_config_audio_capture;
7591 in->config.rate = config->sample_rate;
7592 in->config.format = pcm_format_from_audio_format(config->format);
7593 in->config.channels = channel_count;
7594 in->sample_rate = config->sample_rate;
7595 in->format = config->format;
7596 frame_size = audio_stream_in_frame_size(&in->stream);
7597 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07007598 config->format,
7599 channel_count,
7600 is_low_latency);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307601 in->config.period_size = buffer_size / frame_size;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007602
Revathi Uddarajud2634032017-12-07 14:42:34 +05307603 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
7604 /* optionally use VOIP usecase depending on config(s) */
7605 ret = adev_update_voice_comm_input_stream(in, config);
7606 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007607
Revathi Uddarajud2634032017-12-07 14:42:34 +05307608 if (ret) {
7609 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
7610 goto err_open;
7611 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007612 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007613 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307614 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7615 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007616 devices, flags, in->format,
7617 in->sample_rate, in->bit_width,
7618 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307619 register_format(in->format, in->supported_formats);
7620 register_channel_mask(in->channel_mask, in->supported_channel_masks);
7621 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307622
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007623 /* This stream could be for sound trigger lab,
7624 get sound trigger pcm if present */
7625 audio_extn_sound_trigger_check_and_get_session(in);
7626
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307627 lock_input_stream(in);
7628 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
7629 pthread_mutex_lock(&adev->lock);
7630 in->card_status = adev->card_status;
7631 pthread_mutex_unlock(&adev->lock);
7632 pthread_mutex_unlock(&in->lock);
7633
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007634 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07007635 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007636 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007637
7638err_open:
7639 free(in);
7640 *stream_in = NULL;
7641 return ret;
7642}
7643
7644static void adev_close_input_stream(struct audio_hw_device *dev,
7645 struct audio_stream_in *stream)
7646{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007647 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007648 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007649 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307650
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307651 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007652
kunleizef40adb2018-12-28 17:50:23 +08007653 /* must deregister from sndmonitor first to prevent races
7654 * between the callback and close_stream
7655 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307656 audio_extn_snd_mon_unregister_listener(stream);
7657
kunleizef40adb2018-12-28 17:50:23 +08007658 /* Disable echo reference if there are no active input, hfp call
7659 * and sound trigger while closing input stream
7660 */
7661 if (!adev->active_input &&
7662 !audio_extn_hfp_is_active(adev) &&
7663 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8405edd2018-11-29 15:04:56 +08007664 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleizef40adb2018-12-28 17:50:23 +08007665 else
7666 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307667
Pallavid7c7a272018-01-16 11:22:55 +05307668 if (in == NULL) {
7669 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
7670 return;
7671 }
7672
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007673 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307674 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007675 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307676 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007677 if (ret != 0)
7678 ALOGE("%s: Compress voip input cannot be closed, error:%d",
7679 __func__, ret);
7680 } else
7681 in_standby(&stream->common);
7682
Revathi Uddarajud2634032017-12-07 14:42:34 +05307683 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07007684 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007685 audio_extn_ssr_deinit();
7686 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007687
Garmond Leunge2433c32017-09-28 21:51:22 -07007688 if (audio_extn_ffv_get_stream() == in) {
7689 audio_extn_ffv_stream_deinit();
7690 }
7691
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307692 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07007693 audio_extn_compr_cap_format_supported(in->config.format))
7694 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05307695
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307696 if (audio_extn_cin_attached_usecase(in->usecase))
7697 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007698
Mingming Yinfd7607b2016-01-22 12:48:44 -08007699 if (in->is_st_session) {
7700 ALOGV("%s: sound trigger pcm stop lab", __func__);
7701 audio_extn_sound_trigger_stop_lab(in);
7702 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007703 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307704 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007705 return;
7706}
7707
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307708int adev_create_audio_patch(struct audio_hw_device *dev,
7709 unsigned int num_sources,
7710 const struct audio_port_config *sources,
7711 unsigned int num_sinks,
7712 const struct audio_port_config *sinks,
7713 audio_patch_handle_t *handle)
7714{
7715
7716
7717 return audio_extn_hw_loopback_create_audio_patch(dev,
7718 num_sources,
7719 sources,
7720 num_sinks,
7721 sinks,
7722 handle);
7723
7724}
7725
7726int adev_release_audio_patch(struct audio_hw_device *dev,
7727 audio_patch_handle_t handle)
7728{
7729 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
7730}
7731
7732int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
7733{
7734 return audio_extn_hw_loopback_get_audio_port(dev, config);
7735}
7736
7737int adev_set_audio_port_config(struct audio_hw_device *dev,
7738 const struct audio_port_config *config)
7739{
7740 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
7741}
7742
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007743static int adev_dump(const audio_hw_device_t *device __unused,
7744 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007745{
7746 return 0;
7747}
7748
7749static int adev_close(hw_device_t *device)
7750{
Preetam Singh Ranawat624cc802019-06-24 15:11:28 +05307751 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07007752
Preetam Singh Ranawat624cc802019-06-24 15:11:28 +05307753 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07007754 return 0;
7755
7756 pthread_mutex_lock(&adev_init_lock);
7757
7758 if ((--audio_device_ref_count) == 0) {
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05307759 if (amplifier_close() != 0)
7760 ALOGE("Amplifier close failed");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307761 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007762 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08007763 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307764 audio_extn_utils_release_streams_cfg_lists(
7765 &adev->streams_output_cfg_list,
7766 &adev->streams_input_cfg_list);
Sidipotu Ashokafffd202019-05-06 15:41:56 +05307767 if (audio_extn_qap_is_enabled())
7768 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307769 if (audio_extn_qaf_is_enabled())
7770 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007771 audio_route_free(adev->audio_route);
Weiyin Jiang902f7d12019-03-05 23:39:45 +08007772 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07007773 free(adev->snd_dev_ref_cnt);
7774 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007775 if (adev->adm_deinit)
7776 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307777 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007778 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307779 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307780 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007781 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307782 if (adev->device_cfg_params) {
7783 free(adev->device_cfg_params);
7784 adev->device_cfg_params = NULL;
7785 }
Derek Chencdd17c72014-11-24 12:39:14 -08007786 if(adev->ext_hw_plugin)
7787 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Kiran Kandi910e1862013-10-29 13:29:42 -07007788 free(device);
7789 adev = NULL;
7790 }
Balázs Triszka6e101332018-02-26 22:11:10 +01007791
7792 us_deinit();
7793
Kiran Kandi910e1862013-10-29 13:29:42 -07007794 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchaa1358992018-11-14 13:25:08 +05307795 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007796 return 0;
7797}
7798
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007799/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
7800 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
7801 * just that it _might_ work.
7802 */
7803static int period_size_is_plausible_for_low_latency(int period_size)
7804{
7805 switch (period_size) {
7806 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07007807 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007808 case 240:
7809 case 320:
7810 case 480:
7811 return 1;
7812 default:
7813 return 0;
7814 }
7815}
7816
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307817static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
7818{
7819 bool is_snd_card_status = false;
7820 bool is_ext_device_status = false;
7821 char value[32];
7822 int card = -1;
7823 card_status_t status;
7824
7825 if (cookie != adev || !parms)
7826 return;
7827
7828 if (!parse_snd_card_status(parms, &card, &status)) {
7829 is_snd_card_status = true;
7830 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
7831 is_ext_device_status = true;
7832 } else {
7833 // not a valid event
7834 return;
7835 }
7836
7837 pthread_mutex_lock(&adev->lock);
7838 if (card == adev->snd_card || is_ext_device_status) {
7839 if (is_snd_card_status && adev->card_status != status) {
7840 adev->card_status = status;
7841 platform_snd_card_update(adev->platform, status);
7842 audio_extn_fm_set_parameters(adev, parms);
7843 } else if (is_ext_device_status) {
7844 platform_set_parameters(adev->platform, parms);
7845 }
7846 }
7847 pthread_mutex_unlock(&adev->lock);
7848 return;
7849}
7850
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307851/* out and adev lock held */
7852static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
7853{
7854 struct audio_usecase *uc_info;
7855 float left_p;
7856 float right_p;
7857 audio_devices_t devices;
7858
7859 uc_info = get_usecase_from_list(adev, out->usecase);
7860 if (uc_info == NULL) {
7861 ALOGE("%s: Could not find the usecase (%d) in the list",
7862 __func__, out->usecase);
7863 return -EINVAL;
7864 }
7865
7866 ALOGD("%s: enter: usecase(%d: %s)", __func__,
7867 out->usecase, use_case_table[out->usecase]);
7868
7869 if (restore) {
7870 // restore A2DP device for active usecases and unmute if required
7871 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
7872 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
7873 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
7874 select_devices(adev, uc_info->id);
7875 pthread_mutex_lock(&out->compr_mute_lock);
7876 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7877 (out->a2dp_compress_mute)) {
7878 out->a2dp_compress_mute = false;
7879 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
7880 }
7881 pthread_mutex_unlock(&out->compr_mute_lock);
7882 }
7883 } else {
7884 // mute compress stream if suspended
7885 pthread_mutex_lock(&out->compr_mute_lock);
7886 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7887 (!out->a2dp_compress_mute)) {
7888 if (!out->standby) {
7889 ALOGD("%s: selecting speaker and muting stream", __func__);
7890 devices = out->devices;
7891 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
7892 left_p = out->volume_l;
7893 right_p = out->volume_r;
7894 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7895 compress_pause(out->compr);
7896 out_set_compr_volume(&out->stream, (float)0, (float)0);
7897 out->a2dp_compress_mute = true;
7898 select_devices(adev, out->usecase);
7899 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7900 compress_resume(out->compr);
7901 out->devices = devices;
7902 out->volume_l = left_p;
7903 out->volume_r = right_p;
7904 }
7905 }
7906 pthread_mutex_unlock(&out->compr_mute_lock);
7907 }
7908 ALOGV("%s: exit", __func__);
7909 return 0;
7910}
7911
7912int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
7913{
7914 int ret = 0;
7915
7916 lock_output_stream(out);
7917 pthread_mutex_lock(&adev->lock);
7918
7919 ret = check_a2dp_restore_l(adev, out, restore);
7920
7921 pthread_mutex_unlock(&adev->lock);
7922 pthread_mutex_unlock(&out->lock);
7923 return ret;
7924}
7925
Haynes Mathew George01156f92018-04-13 15:29:54 -07007926void adev_on_battery_status_changed(bool charging)
7927{
7928 pthread_mutex_lock(&adev->lock);
7929 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
7930 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08007931 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07007932 pthread_mutex_unlock(&adev->lock);
7933}
7934
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007935static int adev_open(const hw_module_t *module, const char *name,
7936 hw_device_t **device)
7937{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307938 int ret;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05307939 char mixer_ctl_name[128] = {0};
7940 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307941
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007942 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007943 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
7944
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007945 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07007946 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007947 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07007948 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007949 ALOGD("%s: returning existing instance of adev", __func__);
7950 ALOGD("%s: exit", __func__);
7951 pthread_mutex_unlock(&adev_init_lock);
7952 return 0;
7953 }
7954
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007955 adev = calloc(1, sizeof(struct audio_device));
7956
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007957 if (!adev) {
7958 pthread_mutex_unlock(&adev_init_lock);
7959 return -ENOMEM;
7960 }
7961
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007962 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
7963
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05307964#ifdef DYNAMIC_LOG_ENABLED
7965 register_for_dynamic_logging("hal");
7966#endif
7967
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007968 adev->device.common.tag = HARDWARE_DEVICE_TAG;
7969 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7970 adev->device.common.module = (struct hw_module_t *)module;
7971 adev->device.common.close = adev_close;
7972
7973 adev->device.init_check = adev_init_check;
7974 adev->device.set_voice_volume = adev_set_voice_volume;
7975 adev->device.set_master_volume = adev_set_master_volume;
7976 adev->device.get_master_volume = adev_get_master_volume;
7977 adev->device.set_master_mute = adev_set_master_mute;
7978 adev->device.get_master_mute = adev_get_master_mute;
7979 adev->device.set_mode = adev_set_mode;
7980 adev->device.set_mic_mute = adev_set_mic_mute;
7981 adev->device.get_mic_mute = adev_get_mic_mute;
7982 adev->device.set_parameters = adev_set_parameters;
7983 adev->device.get_parameters = adev_get_parameters;
7984 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
7985 adev->device.open_output_stream = adev_open_output_stream;
7986 adev->device.close_output_stream = adev_close_output_stream;
7987 adev->device.open_input_stream = adev_open_input_stream;
7988 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307989 adev->device.create_audio_patch = adev_create_audio_patch;
7990 adev->device.release_audio_patch = adev_release_audio_patch;
7991 adev->device.get_audio_port = adev_get_audio_port;
7992 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007993 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307994 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007995
7996 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007997 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08007998 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007999 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008000 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008001 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08008002 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07008003 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308004 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07008005 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07008006 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008007 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08008008 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08008009 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008010 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05308011 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308012 adev->perf_lock_opts[0] = 0x101;
8013 adev->perf_lock_opts[1] = 0x20E;
8014 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008015 adev->dsp_bit_width_enforce_mode = 0;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05308016 adev->use_old_pspd_mix_ctrl = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008018 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07008019 adev->platform = platform_init(adev);
8020 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008021 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008022 free(adev->snd_dev_ref_cnt);
8023 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008024 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07008025 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8026 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08008027 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008028 return -EINVAL;
8029 }
Eric Laurentc4aef752013-09-12 17:45:53 -07008030
Sidipotu Ashokafffd202019-05-06 15:41:56 +05308031 if (audio_extn_qap_is_enabled()) {
8032 ret = audio_extn_qap_init(adev);
8033 if (ret < 0) {
8034 pthread_mutex_destroy(&adev->lock);
8035 free(adev);
8036 adev = NULL;
8037 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8038 *device = NULL;
8039 pthread_mutex_unlock(&adev_init_lock);
8040 return ret;
8041 }
8042 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
8043 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
8044 }
8045
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308046 if (audio_extn_qaf_is_enabled()) {
8047 ret = audio_extn_qaf_init(adev);
8048 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008049 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308050 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008051 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308052 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8053 *device = NULL;
8054 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308055 return ret;
8056 }
8057
8058 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
8059 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
8060 }
8061
Derek Chencdd17c72014-11-24 12:39:14 -08008062 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
8063
Eric Laurentc4aef752013-09-12 17:45:53 -07008064 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
8065 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
8066 if (adev->visualizer_lib == NULL) {
8067 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
8068 } else {
8069 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
8070 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008071 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008072 "visualizer_hal_start_output");
8073 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008074 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008075 "visualizer_hal_stop_output");
8076 }
8077 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05308078 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08008079 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08008080 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308081 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008082 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07008083
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008084 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
8085 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
8086 if (adev->offload_effects_lib == NULL) {
8087 ALOGE("%s: DLOPEN failed for %s", __func__,
8088 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8089 } else {
8090 ALOGV("%s: DLOPEN successful for %s", __func__,
8091 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8092 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05308093 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008094 "offload_effects_bundle_hal_start_output");
8095 adev->offload_effects_stop_output =
8096 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
8097 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008098 adev->offload_effects_set_hpx_state =
8099 (int (*)(bool))dlsym(adev->offload_effects_lib,
8100 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05308101 adev->offload_effects_get_parameters =
8102 (void (*)(struct str_parms *, struct str_parms *))
8103 dlsym(adev->offload_effects_lib,
8104 "offload_effects_bundle_get_parameters");
8105 adev->offload_effects_set_parameters =
8106 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
8107 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008108 }
8109 }
8110
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008111 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
8112 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
8113 if (adev->adm_lib == NULL) {
8114 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
8115 } else {
8116 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
8117 adev->adm_init = (adm_init_t)
8118 dlsym(adev->adm_lib, "adm_init");
8119 adev->adm_deinit = (adm_deinit_t)
8120 dlsym(adev->adm_lib, "adm_deinit");
8121 adev->adm_register_input_stream = (adm_register_input_stream_t)
8122 dlsym(adev->adm_lib, "adm_register_input_stream");
8123 adev->adm_register_output_stream = (adm_register_output_stream_t)
8124 dlsym(adev->adm_lib, "adm_register_output_stream");
8125 adev->adm_deregister_stream = (adm_deregister_stream_t)
8126 dlsym(adev->adm_lib, "adm_deregister_stream");
8127 adev->adm_request_focus = (adm_request_focus_t)
8128 dlsym(adev->adm_lib, "adm_request_focus");
8129 adev->adm_abandon_focus = (adm_abandon_focus_t)
8130 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008131 adev->adm_set_config = (adm_set_config_t)
8132 dlsym(adev->adm_lib, "adm_set_config");
8133 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
8134 dlsym(adev->adm_lib, "adm_request_focus_v2");
8135 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
8136 dlsym(adev->adm_lib, "adm_is_noirq_avail");
8137 adev->adm_on_routing_change = (adm_on_routing_change_t)
8138 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008139 }
8140 }
8141
Mingming Yin514a8bc2014-07-29 15:22:21 -07008142 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008143 //initialize this to false for now,
8144 //this will be set to true through set param
8145 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07008146
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07008147 audio_extn_ds2_enable(adev);
Balázs Triszka6e101332018-02-26 22:11:10 +01008148
8149 us_init(adev);
8150
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05308151 if (amplifier_open(adev) != 0)
8152 ALOGE("Amplifier initialization failed");
8153
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008154 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008155 adev->dsp_bit_width_enforce_mode =
8156 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008157
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308158 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
8159 &adev->streams_output_cfg_list,
8160 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008161
Kiran Kandi910e1862013-10-29 13:29:42 -07008162 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008163
8164 char value[PROPERTY_VALUE_MAX];
8165 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008166 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008167 trial = atoi(value);
8168 if (period_size_is_plausible_for_low_latency(trial)) {
8169 pcm_config_low_latency.period_size = trial;
8170 pcm_config_low_latency.start_threshold = trial / 4;
8171 pcm_config_low_latency.avail_min = trial / 4;
8172 configured_low_latency_capture_period_size = trial;
8173 }
8174 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008175 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008176 trial = atoi(value);
8177 if (period_size_is_plausible_for_low_latency(trial)) {
8178 configured_low_latency_capture_period_size = trial;
8179 }
8180 }
8181
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08008182 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
8183
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008184 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008185 af_period_multiplier = atoi(value);
8186 if (af_period_multiplier < 0)
8187 af_period_multiplier = 2;
8188 else if (af_period_multiplier > 4)
8189 af_period_multiplier = 4;
8190
8191 ALOGV("new period_multiplier = %d", af_period_multiplier);
8192 }
8193
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008194 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008195 pthread_mutex_unlock(&adev_init_lock);
8196
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008197 if (adev->adm_init)
8198 adev->adm_data = adev->adm_init();
8199
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308200 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308201 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008202 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308203
8204 audio_extn_snd_mon_init();
8205 pthread_mutex_lock(&adev->lock);
8206 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
8207 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07008208 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
8209 /*
8210 * if the battery state callback happens before charging can be queried,
8211 * it will be guarded with the adev->lock held in the cb function and so
8212 * the callback value will reflect the latest state
8213 */
8214 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308215 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08008216 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
8217 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308218 /* Allocate memory for Device config params */
8219 adev->device_cfg_params = (struct audio_device_config_param*)
8220 calloc(platform_get_max_codec_backend(),
8221 sizeof(struct audio_device_config_param));
8222 if (adev->device_cfg_params == NULL)
8223 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308224
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05308225 /*
8226 * Check if new PSPD matrix mixer control is supported. If not
8227 * supported, then set flag so that old mixer ctrl is sent while
8228 * sending pspd coefficients on older kernel version. Query mixer
8229 * control for default pcm id and channel value one.
8230 */
8231 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
8232 "AudStr %d ChMixer Weight Ch %d", 0, 1);
8233
8234 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
8235 if (!ctl) {
8236 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
8237 __func__, mixer_ctl_name);
8238 adev->use_old_pspd_mix_ctrl = true;
8239 }
8240
Eric Laurent994a6932013-07-17 11:51:42 -07008241 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008242 return 0;
8243}
8244
8245static struct hw_module_methods_t hal_module_methods = {
8246 .open = adev_open,
8247};
8248
8249struct audio_module HAL_MODULE_INFO_SYM = {
8250 .common = {
8251 .tag = HARDWARE_MODULE_TAG,
8252 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
8253 .hal_api_version = HARDWARE_HAL_API_VERSION,
8254 .id = AUDIO_HARDWARE_MODULE_ID,
8255 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08008256 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008257 .methods = &hal_module_methods,
8258 },
8259};