blob: 54d01c0130ca65f221b77cf6b556ba732630a577 [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
Michael Bestas8e923ec2019-12-10 02:13:27 +020058#include <log/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 }
Lakshman Chaluvaraju3fe883a2019-06-24 10:04:52 +05303735 // if fm is active route on selected device in UI
3736 audio_extn_fm_route_on_selected_device(adev, out->devices);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003737 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738 }
3739 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303740 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741 return 0;
3742}
3743
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303744static int out_on_error(struct audio_stream *stream)
3745{
3746 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003747 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303748
3749 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003750 // always send CMD_ERROR for offload streams, this
3751 // is needed e.g. when SSR happens within compress_open
3752 // since the stream is active, offload_callback_thread is also active.
3753 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3754 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003755 }
3756 pthread_mutex_unlock(&out->lock);
3757
3758 status = out_standby(&out->stream.common);
3759
3760 lock_output_stream(out);
3761 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003762 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303763 }
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05303764
3765 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
3766 ALOGD("Setting previous card status if offline");
3767 out->prev_card_status_offline = true;
3768 }
3769
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303770 pthread_mutex_unlock(&out->lock);
3771
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003772 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303773}
3774
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303775/*
3776 *standby implementation without locks, assumes that the callee already
3777 *has taken adev and out lock.
3778 */
3779int out_standby_l(struct audio_stream *stream)
3780{
3781 struct stream_out *out = (struct stream_out *)stream;
3782 struct audio_device *adev = out->dev;
3783
3784 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3785 stream, out->usecase, use_case_table[out->usecase]);
3786
3787 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003788 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303789 if (adev->adm_deregister_stream)
3790 adev->adm_deregister_stream(adev->adm_data, out->handle);
3791
3792 if (is_offload_usecase(out->usecase))
3793 stop_compressed_output_l(out);
3794
3795 out->standby = true;
3796 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3797 voice_extn_compress_voip_close_output_stream(stream);
3798 out->started = 0;
3799 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003800 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303801 return 0;
3802 } else if (!is_offload_usecase(out->usecase)) {
3803 if (out->pcm) {
3804 pcm_close(out->pcm);
3805 out->pcm = NULL;
3806 }
3807 } else {
3808 ALOGD("copl(%p):standby", out);
3809 out->send_next_track_params = false;
3810 out->is_compr_metadata_avail = false;
3811 out->gapless_mdata.encoder_delay = 0;
3812 out->gapless_mdata.encoder_padding = 0;
3813 if (out->compr != NULL) {
3814 compress_close(out->compr);
3815 out->compr = NULL;
3816 }
3817 }
3818 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003819 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303820 }
3821 ALOGD("%s: exit", __func__);
3822 return 0;
3823}
3824
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003825static int out_dump(const struct audio_stream *stream __unused,
3826 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003827{
3828 return 0;
3829}
3830
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003831static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3832{
3833 int ret = 0;
3834 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003835
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003836 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003837 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003838 return -EINVAL;
3839 }
3840
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303841 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003842
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003843 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3844 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303845 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003846 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003847 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3848 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303849 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003850 }
3851
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003852 ALOGV("%s new encoder delay %u and padding %u", __func__,
3853 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3854
3855 return 0;
3856}
3857
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003858static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3859{
3860 return out == adev->primary_output || out == adev->voice_tx_output;
3861}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003862
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303863// note: this call is safe only if the stream_cb is
3864// removed first in close_output_stream (as is done now).
3865static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3866{
3867 if (!stream || !parms)
3868 return;
3869
3870 struct stream_out *out = (struct stream_out *)stream;
3871 struct audio_device *adev = out->dev;
3872
3873 card_status_t status;
3874 int card;
3875 if (parse_snd_card_status(parms, &card, &status) < 0)
3876 return;
3877
3878 pthread_mutex_lock(&adev->lock);
3879 bool valid_cb = (card == adev->snd_card);
3880 pthread_mutex_unlock(&adev->lock);
3881
3882 if (!valid_cb)
3883 return;
3884
3885 lock_output_stream(out);
3886 if (out->card_status != status)
3887 out->card_status = status;
3888 pthread_mutex_unlock(&out->lock);
3889
3890 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3891 use_case_table[out->usecase],
3892 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3893
Aditya Bavanari9aa0b922019-02-05 17:44:57 +05303894 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303895 out_on_error(stream);
Aditya Bavanari9aa0b922019-02-05 17:44:57 +05303896 if (voice_is_call_state_active(adev) &&
3897 out == adev->primary_output) {
3898 ALOGD("%s: SSR/PDR occurred, end all calls", __func__);
3899 pthread_mutex_lock(&adev->lock);
3900 voice_stop_call(adev);
3901 adev->mode = AUDIO_MODE_NORMAL;
3902 pthread_mutex_unlock(&adev->lock);
3903 }
3904 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303905 return;
3906}
3907
Kevin Rocardfce19002017-08-07 19:21:36 -07003908static int get_alive_usb_card(struct str_parms* parms) {
3909 int card;
3910 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
3911 !audio_extn_usb_alive(card)) {
3912 return card;
3913 }
3914 return -ENODEV;
3915}
3916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3918{
3919 struct stream_out *out = (struct stream_out *)stream;
3920 struct audio_device *adev = out->dev;
3921 struct str_parms *parms;
3922 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003923 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303924 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003925 bool reconfig = false;
3926 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003927
sangwoobc677242013-08-08 16:53:43 +09003928 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003929 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303931 if (!parms)
3932 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003933 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3934 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003935 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003936 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003937 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003938
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003939 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003940 * When HDMI cable is unplugged the music playback is paused and
3941 * the policy manager sends routing=0. But the audioflinger continues
3942 * to write data until standby time (3sec). As the HDMI core is
3943 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003944 * Avoid this by routing audio to speaker until standby.
3945 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003946 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3947 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303948 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003949 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3950 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003951 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303952 /*
3953 * When A2DP is disconnected the
3954 * music playback is paused and the policy manager sends routing=0
3955 * But the audioflingercontinues to write data until standby time
3956 * (3sec). As BT is turned off, the write gets blocked.
3957 * Avoid this by routing audio to speaker until standby.
3958 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003959 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07003960 (val == AUDIO_DEVICE_NONE) &&
3961 !audio_extn_a2dp_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303962 val = AUDIO_DEVICE_OUT_SPEAKER;
3963 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05303964 /*
3965 * When USB headset is disconnected the music platback paused
3966 * and the policy manager send routing=0. But if the USB is connected
3967 * back before the standby time, AFE is not closed and opened
3968 * when USB is connected back. So routing to speker will guarantee
3969 * AFE reconfiguration and AFE will be opend once USB is connected again
3970 */
3971 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
3972 (val == AUDIO_DEVICE_NONE) &&
3973 !audio_extn_usb_connected(parms)) {
3974 val = AUDIO_DEVICE_OUT_SPEAKER;
3975 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303976 /* To avoid a2dp to sco overlapping / BT device improper state
3977 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303978 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303979 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3980 if (!audio_extn_a2dp_is_ready()) {
3981 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3982 //combo usecase just by pass a2dp
3983 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303984 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303985 } else {
3986 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3987 /* update device to a2dp and don't route as BT returned error
3988 * However it is still possible a2dp routing called because
3989 * of current active device disconnection (like wired headset)
3990 */
3991 out->devices = val;
3992 pthread_mutex_unlock(&out->lock);
3993 pthread_mutex_unlock(&adev->lock);
3994 goto error;
3995 }
3996 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303997 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003998
3999 audio_devices_t new_dev = val;
4000
4001 // Workaround: If routing to an non existing usb device, fail gracefully
4002 // The routing request will otherwise block during 10 second
4003 int card;
4004 if (audio_is_usb_out_device(new_dev) &&
4005 (card = get_alive_usb_card(parms)) >= 0) {
4006
4007 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4008 pthread_mutex_unlock(&adev->lock);
4009 pthread_mutex_unlock(&out->lock);
4010 ret = -ENOSYS;
4011 goto routing_fail;
4012 }
4013
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004014 /*
4015 * select_devices() call below switches all the usecases on the same
4016 * backend to the new device. Refer to check_usecases_codec_backend() in
4017 * the select_devices(). But how do we undo this?
4018 *
4019 * For example, music playback is active on headset (deep-buffer usecase)
4020 * and if we go to ringtones and select a ringtone, low-latency usecase
4021 * will be started on headset+speaker. As we can't enable headset+speaker
4022 * and headset devices at the same time, select_devices() switches the music
4023 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4024 * So when the ringtone playback is completed, how do we undo the same?
4025 *
4026 * We are relying on the out_set_parameters() call on deep-buffer output,
4027 * once the ringtone playback is ended.
4028 * NOTE: We should not check if the current devices are same as new devices.
4029 * Because select_devices() must be called to switch back the music
4030 * playback to headset.
4031 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004032 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004033 audio_devices_t new_dev = val;
4034 bool same_dev = out->devices == new_dev;
4035 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004036
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004037 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004038 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004039 if (adev->mode == AUDIO_MODE_IN_CALL) {
4040 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004041 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4042 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4043 audio_extn_usb_set_service_interval(true /*playback*/,
4044 service_interval,
4045 &reconfig);
4046 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4047 }
4048 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004049 }
4050 } else {
4051 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004052 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004053 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004054 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004055
4056 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004057 if (!same_dev) {
4058 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304059 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4060 adev->perf_lock_opts,
4061 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004062 if (adev->adm_on_routing_change)
4063 adev->adm_on_routing_change(adev->adm_data,
4064 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004065 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304066 if (!bypass_a2dp) {
4067 select_devices(adev, out->usecase);
4068 } else {
4069 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
4070 select_devices(adev, out->usecase);
4071 out->devices = new_dev;
4072 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004073
4074 if (!same_dev) {
4075 // on device switch force swap, lower functions will make sure
4076 // to check if swap is allowed or not.
4077 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304078 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004079 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304080 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4081 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08004082 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304083 pthread_mutex_lock(&out->compr_mute_lock);
4084 out->a2dp_compress_mute = false;
4085 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4086 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004087 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4088 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304089 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004090 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004091 }
4092
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004094 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004095 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004096 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004097
4098 if (out == adev->primary_output) {
4099 pthread_mutex_lock(&adev->lock);
4100 audio_extn_set_parameters(adev, parms);
4101 pthread_mutex_unlock(&adev->lock);
4102 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004103 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004104 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004105 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004106
4107 audio_extn_dts_create_state_notifier_node(out->usecase);
4108 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4109 popcount(out->channel_mask),
4110 out->playback_started);
4111
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004112 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004113 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004114
Surendar Karka5a18a7a2018-04-26 11:28:38 +05304115 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4116 sizeof(value));
4117 if (err >= 0) {
4118 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4119 audio_extn_send_dual_mono_mixing_coefficients(out);
4120 }
4121
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304122 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4123 if (err >= 0) {
4124 strlcpy(out->profile, value, sizeof(out->profile));
4125 ALOGV("updating stream profile with value '%s'", out->profile);
4126 lock_output_stream(out);
4127 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4128 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004129 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304130 out->sample_rate, out->bit_width,
4131 out->channel_mask, out->profile,
4132 &out->app_type_cfg);
4133 pthread_mutex_unlock(&out->lock);
4134 }
4135
Alexy Joseph98988832017-01-13 14:56:59 -08004136 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004137 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4138 // and vendor.audio.hal.output.suspend.supported is set to true
4139 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004140 //check suspend parameter only for low latency and if the property
4141 //is enabled
4142 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4143 ALOGI("%s: got suspend_playback %s", __func__, value);
4144 lock_output_stream(out);
4145 if (!strncmp(value, "false", 5)) {
4146 //suspend_playback=false is supposed to set QOS value back to 75%
4147 //the mixer control sent with value Enable will achieve that
4148 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4149 } else if (!strncmp (value, "true", 4)) {
4150 //suspend_playback=true is supposed to remove QOS value
4151 //resetting the mixer control will set the default value
4152 //for the mixer control which is Disable and this removes the QOS vote
4153 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4154 } else {
4155 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4156 " got %s", __func__, value);
4157 ret = -1;
4158 }
4159
4160 if (ret != 0) {
4161 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4162 __func__, out->pm_qos_mixer_path, ret);
4163 }
4164
4165 pthread_mutex_unlock(&out->lock);
4166 }
4167 }
4168 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004169 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304170error:
Eric Laurent994a6932013-07-17 11:51:42 -07004171 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004172 return ret;
4173}
4174
Ramjee Singhacef98f2019-06-28 11:01:25 +05304175#if ANDROID_PLATFORM_SDK_VERSION >= 29
4176static int in_set_microphone_direction(const struct audio_stream_in *stream,
4177 audio_microphone_direction_t dir) {
4178 int ret_val = -ENOSYS;
4179 (void)stream;
4180 (void)dir;
4181 ALOGV("---- in_set_microphone_direction()");
4182 return ret_val;
4183}
4184
4185static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
4186 int ret_val = -ENOSYS;
4187 (void)zoom;
4188 (void)stream;
4189 ALOGV("---- in_set_microphone_field_dimension()");
4190 return ret_val;
4191}
4192#endif
4193
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004194static bool stream_get_parameter_channels(struct str_parms *query,
4195 struct str_parms *reply,
4196 audio_channel_mask_t *supported_channel_masks) {
4197 int ret = -1;
4198 char value[512];
4199 bool first = true;
4200 size_t i, j;
4201
4202 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4203 ret = 0;
4204 value[0] = '\0';
4205 i = 0;
4206 while (supported_channel_masks[i] != 0) {
4207 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4208 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4209 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304210 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004211
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304212 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004213 first = false;
4214 break;
4215 }
4216 }
4217 i++;
4218 }
4219 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4220 }
4221 return ret == 0;
4222}
4223
4224static bool stream_get_parameter_formats(struct str_parms *query,
4225 struct str_parms *reply,
4226 audio_format_t *supported_formats) {
4227 int ret = -1;
4228 char value[256];
4229 size_t i, j;
4230 bool first = true;
4231
4232 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4233 ret = 0;
4234 value[0] = '\0';
4235 i = 0;
4236 while (supported_formats[i] != 0) {
4237 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4238 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4239 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304240 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004241 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304242 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004243 first = false;
4244 break;
4245 }
4246 }
4247 i++;
4248 }
4249 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4250 }
4251 return ret == 0;
4252}
4253
4254static bool stream_get_parameter_rates(struct str_parms *query,
4255 struct str_parms *reply,
4256 uint32_t *supported_sample_rates) {
4257
4258 int i;
4259 char value[256];
4260 int ret = -1;
4261 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4262 ret = 0;
4263 value[0] = '\0';
4264 i=0;
4265 int cursor = 0;
4266 while (supported_sample_rates[i]) {
4267 int avail = sizeof(value) - cursor;
4268 ret = snprintf(value + cursor, avail, "%s%d",
4269 cursor > 0 ? "|" : "",
4270 supported_sample_rates[i]);
4271 if (ret < 0 || ret >= avail) {
4272 // if cursor is at the last element of the array
4273 // overwrite with \0 is duplicate work as
4274 // snprintf already put a \0 in place.
4275 // else
4276 // we had space to write the '|' at value[cursor]
4277 // (which will be overwritten) or no space to fill
4278 // the first element (=> cursor == 0)
4279 value[cursor] = '\0';
4280 break;
4281 }
4282 cursor += ret;
4283 ++i;
4284 }
4285 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4286 value);
4287 }
4288 return ret >= 0;
4289}
4290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004291static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4292{
4293 struct stream_out *out = (struct stream_out *)stream;
4294 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004295 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004296 char value[256];
4297 struct str_parms *reply = str_parms_create();
4298 size_t i, j;
4299 int ret;
4300 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004301
4302 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004303 if (reply) {
4304 str_parms_destroy(reply);
4305 }
4306 if (query) {
4307 str_parms_destroy(query);
4308 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004309 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4310 return NULL;
4311 }
4312
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004313 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004314 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4315 if (ret >= 0) {
4316 value[0] = '\0';
4317 i = 0;
4318 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004319 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4320 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004322 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004323 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004324 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004325 first = false;
4326 break;
4327 }
4328 }
4329 i++;
4330 }
4331 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4332 str = str_parms_to_str(reply);
4333 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004334 voice_extn_out_get_parameters(out, query, reply);
4335 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004336 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004337
Alexy Joseph62142aa2015-11-16 15:10:34 -08004338
4339 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4340 if (ret >= 0) {
4341 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304342 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4343 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004344 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304345 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004346 } else {
4347 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304348 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004349 }
4350 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004351 if (str)
4352 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004353 str = str_parms_to_str(reply);
4354 }
4355
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004356 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4357 if (ret >= 0) {
4358 value[0] = '\0';
4359 i = 0;
4360 first = true;
4361 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004362 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4363 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004364 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004365 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004366 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004367 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004368 first = false;
4369 break;
4370 }
4371 }
4372 i++;
4373 }
4374 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004375 if (str)
4376 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004377 str = str_parms_to_str(reply);
4378 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004379
4380 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4381 if (ret >= 0) {
4382 value[0] = '\0';
4383 i = 0;
4384 first = true;
4385 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004386 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4387 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004388 if (!first) {
4389 strlcat(value, "|", sizeof(value));
4390 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004391 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004392 first = false;
4393 break;
4394 }
4395 }
4396 i++;
4397 }
4398 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4399 if (str)
4400 free(str);
4401 str = str_parms_to_str(reply);
4402 }
4403
Alexy Joseph98988832017-01-13 14:56:59 -08004404 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4405 //only low latency track supports suspend_resume
4406 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004407 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004408 if (str)
4409 free(str);
4410 str = str_parms_to_str(reply);
4411 }
4412
4413
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004414 str_parms_destroy(query);
4415 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004416 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004417 return str;
4418}
4419
4420static uint32_t out_get_latency(const struct audio_stream_out *stream)
4421{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004422 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004424 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004425
Alexy Josephaa54c872014-12-03 02:46:47 -08004426 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304427 lock_output_stream(out);
4428 latency = audio_extn_utils_compress_get_dsp_latency(out);
4429 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004430 } else if ((out->realtime) ||
4431 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004432 // since the buffer won't be filled up faster than realtime,
4433 // return a smaller number
4434 if (out->config.rate)
4435 period_ms = (out->af_period_multiplier * out->config.period_size *
4436 1000) / (out->config.rate);
4437 else
4438 period_ms = 0;
4439 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004440 } else {
4441 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004442 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004443 }
4444
yidongh0515e042017-07-06 15:00:34 +08004445 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004446 latency += audio_extn_a2dp_get_encoder_latency();
4447
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304448 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004449 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004450}
4451
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304452static float AmpToDb(float amplification)
4453{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304454 float db = DSD_VOLUME_MIN_DB;
4455 if (amplification > 0) {
4456 db = 20 * log10(amplification);
4457 if(db < DSD_VOLUME_MIN_DB)
4458 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304459 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304460 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304461}
4462
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004463static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4464 float right)
4465{
4466 struct stream_out *out = (struct stream_out *)stream;
4467 long volume = 0;
4468 char mixer_ctl_name[128] = "";
4469 struct audio_device *adev = out->dev;
4470 struct mixer_ctl *ctl = NULL;
4471 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4472 PCM_PLAYBACK);
4473
4474 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4475 "Playback %d Volume", pcm_device_id);
4476 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4477 if (!ctl) {
4478 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4479 __func__, mixer_ctl_name);
4480 return -EINVAL;
4481 }
4482 if (left != right)
4483 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4484 __func__, left, right);
4485 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4486 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4487 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4488 __func__, mixer_ctl_name, volume);
4489 return -EINVAL;
4490 }
4491 return 0;
4492}
4493
4494
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304495static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4496 float right)
4497{
4498 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304499 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304500 char mixer_ctl_name[128];
4501 struct audio_device *adev = out->dev;
4502 struct mixer_ctl *ctl;
4503 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4504 PCM_PLAYBACK);
4505
4506 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4507 "Compress Playback %d Volume", pcm_device_id);
4508 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4509 if (!ctl) {
4510 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4511 __func__, mixer_ctl_name);
4512 return -EINVAL;
4513 }
4514 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4515 __func__, mixer_ctl_name, left, right);
4516 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4517 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4518 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4519
4520 return 0;
4521}
4522
Zhou Song2b8f28f2017-09-11 10:51:38 +08004523static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4524 float right)
4525{
4526 struct stream_out *out = (struct stream_out *)stream;
4527 char mixer_ctl_name[] = "App Type Gain";
4528 struct audio_device *adev = out->dev;
4529 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304530 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004531
4532 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4533 if (!ctl) {
4534 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4535 __func__, mixer_ctl_name);
4536 return -EINVAL;
4537 }
4538
4539 set_values[0] = 0; //0: Rx Session 1:Tx Session
4540 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304541 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4542 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004543
4544 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4545 return 0;
4546}
4547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004548static int out_set_volume(struct audio_stream_out *stream, float left,
4549 float right)
4550{
Eric Laurenta9024de2013-04-04 09:19:12 -07004551 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004552 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304553 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004554
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004555 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
4556
Eric Laurenta9024de2013-04-04 09:19:12 -07004557 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4558 /* only take left channel into account: the API is for stereo anyway */
4559 out->muted = (left == 0.0f);
4560 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004561 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304562 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004563 /*
4564 * Set mute or umute on HDMI passthrough stream.
4565 * Only take left channel into account.
4566 * Mute is 0 and unmute 1
4567 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304568 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304569 } else if (out->format == AUDIO_FORMAT_DSD){
4570 char mixer_ctl_name[128] = "DSD Volume";
4571 struct audio_device *adev = out->dev;
4572 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4573
4574 if (!ctl) {
4575 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4576 __func__, mixer_ctl_name);
4577 return -EINVAL;
4578 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304579 volume[0] = (long)(AmpToDb(left));
4580 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304581 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4582 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004583 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304584 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004585 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304586 if (!out->a2dp_compress_mute)
4587 ret = out_set_compr_volume(stream, left, right);
4588 out->volume_l = left;
4589 out->volume_r = right;
4590 pthread_mutex_unlock(&out->compr_mute_lock);
4591 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004592 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004593 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004594 if (!out->standby)
4595 ret = out_set_voip_volume(stream, left, right);
4596 out->volume_l = left;
4597 out->volume_r = right;
4598 return ret;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004599 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4600 ALOGV("%s: MMAP set volume called", __func__);
4601 if (!out->standby)
4602 ret = out_set_mmap_volume(stream, left, right);
4603 out->volume_l = left;
4604 out->volume_r = right;
4605 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004606 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004607
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004608 return -ENOSYS;
4609}
4610
Zhou Songc9672822017-08-16 16:01:39 +08004611static void update_frames_written(struct stream_out *out, size_t bytes)
4612{
4613 size_t bpf = 0;
4614
4615 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4616 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4617 bpf = 1;
4618 else if (!is_offload_usecase(out->usecase))
4619 bpf = audio_bytes_per_sample(out->format) *
4620 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004621
4622 pthread_mutex_lock(&out->position_query_lock);
4623 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004624 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004625 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4626 }
4627 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004628}
4629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004630static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4631 size_t bytes)
4632{
4633 struct stream_out *out = (struct stream_out *)stream;
4634 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004635 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304636 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004637 const size_t frame_size = audio_stream_out_frame_size(stream);
4638 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05304639 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004640
Haynes Mathew George380745d2017-10-04 15:27:45 -07004641 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004642 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304643
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304644 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004645
Dhananjay Kumarac341582017-02-23 23:42:25 +05304646 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304647 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304648 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4649 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004650 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304651 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304652 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304653 ALOGD(" %s: sound card is not active/SSR state", __func__);
4654 ret= -EIO;
4655 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304656 }
4657 }
4658
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304659 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304660 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304661 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304662 goto exit;
4663 }
4664
Haynes Mathew George16081042017-05-31 17:16:49 -07004665 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4666 ret = -EINVAL;
4667 goto exit;
4668 }
4669
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304670 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4671 !out->is_iec61937_info_available) {
4672
4673 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4674 out->is_iec61937_info_available = true;
4675 } else if (audio_extn_passthru_is_enabled()) {
4676 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304677 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304678
4679 if((out->format == AUDIO_FORMAT_DTS) ||
4680 (out->format == AUDIO_FORMAT_DTS_HD)) {
4681 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4682 buffer, bytes);
4683 if (ret) {
4684 if (ret != -ENOSYS) {
4685 out->is_iec61937_info_available = false;
4686 ALOGD("iec61937 transmission info not yet updated retry");
4687 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304688 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304689 /* if stream has started and after that there is
4690 * stream config change (iec transmission config)
4691 * then trigger select_device to update backend configuration.
4692 */
4693 out->stream_config_changed = true;
4694 pthread_mutex_lock(&adev->lock);
4695 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304696 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4697 ret = -EINVAL;
4698 goto exit;
4699 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304700 pthread_mutex_unlock(&adev->lock);
4701 out->stream_config_changed = false;
4702 out->is_iec61937_info_available = true;
4703 }
4704 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304705
Garmond Leung317cbf12017-09-13 16:20:50 -07004706 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304707 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4708 (out->is_iec61937_info_available == true)) {
4709 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4710 ret = -EINVAL;
4711 goto exit;
4712 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304713 }
4714 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304715
4716 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4717 (audio_extn_a2dp_is_suspended())) {
4718 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4719 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304720 ret = -EIO;
4721 goto exit;
4722 }
4723 }
4724 }
4725
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004726 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004727 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004728 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004729 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4730 ret = voice_extn_compress_voip_start_output_stream(out);
4731 else
4732 ret = start_output_stream(out);
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05304733
4734 if (ret == 0)
4735 amplifier_output_stream_start(stream,
4736 is_offload_usecase(out->usecase));
4737
Eric Laurent150dbfe2013-02-27 14:31:02 -08004738 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004739 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004740 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004741 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004742 goto exit;
4743 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304744 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004745 if (last_known_cal_step != -1) {
4746 ALOGD("%s: retry previous failed cal level set", __func__);
4747 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304748 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004749 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304750
4751 if ((out->is_iec61937_info_available == true) &&
4752 (audio_extn_passthru_is_passthrough_stream(out))&&
4753 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4754 ret = -EINVAL;
4755 goto exit;
4756 }
Surendar Karka5a18a7a2018-04-26 11:28:38 +05304757 if (out->set_dual_mono)
4758 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004759 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004760
Ashish Jain81eb2a82015-05-13 10:52:34 +05304761 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004762 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304763 adev->is_channel_status_set = true;
4764 }
4765
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05304766 if ((adev->use_old_pspd_mix_ctrl == true) &&
4767 (out->pspd_coeff_sent == false)) {
4768 /*
4769 * Need to resend pspd coefficients after stream started for
4770 * older kernel version as it does not save the coefficients
4771 * and also stream has to be started for coeff to apply.
4772 */
4773 usecase = get_usecase_from_list(adev, out->usecase);
4774 if (usecase != NULL) {
4775 audio_extn_set_custom_mtmx_params(adev, usecase, true);
4776 out->pspd_coeff_sent = true;
4777 }
4778 }
4779
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004780 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004781 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004782 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004783 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004784 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4785 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304786 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4787 ALOGD("copl(%p):send next track params in gapless", out);
4788 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4789 out->send_next_track_params = false;
4790 out->is_compr_metadata_avail = false;
4791 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004792 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304793 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304794 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004795
Ashish Jain83a6cc22016-06-28 14:34:17 +05304796 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304797 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304798 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304799 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004800 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304801 return -EINVAL;
4802 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304803 audio_format_t dst_format = out->hal_op_format;
4804 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304805
4806 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4807 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4808
Ashish Jain83a6cc22016-06-28 14:34:17 +05304809 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304810 dst_format,
4811 buffer,
4812 src_format,
4813 frames);
4814
Ashish Jain83a6cc22016-06-28 14:34:17 +05304815 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304816 bytes_to_write);
4817
4818 /*Convert written bytes in audio flinger format*/
4819 if (ret > 0)
4820 ret = ((ret * format_to_bitwidth_table[out->format]) /
4821 format_to_bitwidth_table[dst_format]);
4822 }
4823 } else
4824 ret = compress_write(out->compr, buffer, bytes);
4825
Zhou Songc9672822017-08-16 16:01:39 +08004826 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4827 update_frames_written(out, bytes);
4828
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304829 if (ret < 0)
4830 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08004831 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304832 /*msg to cb thread only if non blocking write is enabled*/
4833 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304834 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004835 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304836 } else if (-ENETRESET == ret) {
4837 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304838 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304839 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304840 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004841 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304842 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004843 }
Ashish Jain5106d362016-05-11 19:23:33 +05304844
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304845 /* Call compr start only when non-zero bytes of data is there to be rendered */
4846 if (!out->playback_started && ret > 0) {
4847 int status = compress_start(out->compr);
4848 if (status < 0) {
4849 ret = status;
4850 ALOGE("%s: compr start failed with err %d", __func__, errno);
4851 goto exit;
4852 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004853 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004854 out->playback_started = 1;
4855 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004856
4857 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4858 popcount(out->channel_mask),
4859 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004860 }
4861 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004862 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004863 return ret;
4864 } else {
4865 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004866 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004867 if (out->muted)
4868 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004869 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
4870 __func__, frames, frame_size, bytes_to_write);
4871
Arun Mirpuridbef0c72018-09-12 18:36:10 -07004872 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4873 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004874 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4875 int16_t *src = (int16_t *)buffer;
4876 int16_t *dst = (int16_t *)buffer;
4877
4878 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
4879 out->format != AUDIO_FORMAT_PCM_16_BIT,
4880 "out_write called for incall music use case with wrong properties");
4881
4882 /*
4883 * FIXME: this can be removed once audio flinger mixer supports
4884 * mono output
4885 */
4886
4887 /*
4888 * Code below goes over each frame in the buffer and adds both
4889 * L and R samples and then divides by 2 to convert to mono
4890 */
4891 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
4892 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
4893 }
4894 bytes_to_write /= 2;
4895 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004896
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304897 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004898
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004899 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004900
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004901 if (out->config.rate)
4902 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4903 out->config.rate;
4904
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004905 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004906 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4907
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004908 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004909 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004910 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304911 out->convert_buffer != NULL) {
4912
4913 memcpy_by_audio_format(out->convert_buffer,
4914 out->hal_op_format,
4915 buffer,
4916 out->hal_ip_format,
4917 out->config.period_size * out->config.channels);
4918
4919 ret = pcm_write(out->pcm, out->convert_buffer,
4920 (out->config.period_size *
4921 out->config.channels *
4922 format_to_bitwidth_table[out->hal_op_format]));
4923 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304924 /*
4925 * To avoid underrun in DSP when the application is not pumping
4926 * data at required rate, check for the no. of bytes and ignore
4927 * pcm_write if it is less than actual buffer size.
4928 * It is a work around to a change in compress VOIP driver.
4929 */
4930 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4931 bytes < (out->config.period_size * out->config.channels *
4932 audio_bytes_per_sample(out->format))) {
4933 size_t voip_buf_size =
4934 out->config.period_size * out->config.channels *
4935 audio_bytes_per_sample(out->format);
4936 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4937 __func__, bytes, voip_buf_size);
4938 usleep(((uint64_t)voip_buf_size - bytes) *
4939 1000000 / audio_stream_out_frame_size(stream) /
4940 out_get_sample_rate(&out->stream.common));
4941 ret = 0;
4942 } else
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004943 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304944 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004945
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004946 release_out_focus(out);
4947
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304948 if (ret < 0)
4949 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004950 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304951 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004952 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004953 }
4954
4955exit:
Zhou Songc9672822017-08-16 16:01:39 +08004956 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304957 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304958 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304959 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004960 pthread_mutex_unlock(&out->lock);
4961
4962 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004963 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004964 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304965 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304966 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304967 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304968 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304969 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304970 out->standby = true;
4971 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304972 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304973 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4974 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4975 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004976
4977 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05304978 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004979 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004980 return ret;
4981 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004982 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004983 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004984 return bytes;
4985}
4986
4987static int out_get_render_position(const struct audio_stream_out *stream,
4988 uint32_t *dsp_frames)
4989{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004990 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004991
4992 if (dsp_frames == NULL)
4993 return -EINVAL;
4994
4995 *dsp_frames = 0;
4996 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004997 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304998
4999 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5000 * this operation and adev_close_output_stream(where out gets reset).
5001 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305002 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005003 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305004 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005005 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305006 return 0;
5007 }
5008
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005009 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305010 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305011 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005012 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305013 if (ret < 0)
5014 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005015 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305016 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005017 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305018 if (-ENETRESET == ret) {
5019 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305020 out->card_status = CARD_STATUS_OFFLINE;
5021 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305022 } else if(ret < 0) {
5023 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305024 ret = -EINVAL;
5025 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305026 /*
5027 * Handle corner case where compress session is closed during SSR
5028 * and timestamp is queried
5029 */
5030 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305031 ret = -EINVAL;
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05305032 } else if (out->prev_card_status_offline) {
5033 ALOGE("ERROR: previously sound card was offline,return error");
5034 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305035 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305036 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005037 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305038 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305039 pthread_mutex_unlock(&out->lock);
5040 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005041 } else if (audio_is_linear_pcm(out->format)) {
5042 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005043 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005044 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005045 } else
5046 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005047}
5048
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005049static int out_add_audio_effect(const struct audio_stream *stream __unused,
5050 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005051{
5052 return 0;
5053}
5054
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005055static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5056 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005057{
5058 return 0;
5059}
5060
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005061static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5062 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005063{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305064 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005065}
5066
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005067static int out_get_presentation_position(const struct audio_stream_out *stream,
5068 uint64_t *frames, struct timespec *timestamp)
5069{
5070 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305071 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005072 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005073
Ashish Jain5106d362016-05-11 19:23:33 +05305074 /* below piece of code is not guarded against any lock because audioFliner serializes
5075 * this operation and adev_close_output_stream( where out gets reset).
5076 */
5077 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305078 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005079 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305080 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5081 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5082 return 0;
5083 }
5084
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005085 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005086
Ashish Jain5106d362016-05-11 19:23:33 +05305087 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5088 ret = compress_get_tstamp(out->compr, &dsp_frames,
5089 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005090 // Adjustment accounts for A2dp encoder latency with offload usecases
5091 // Note: Encoder latency is returned in ms.
5092 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5093 unsigned long offset =
5094 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5095 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5096 }
Ashish Jain5106d362016-05-11 19:23:33 +05305097 ALOGVV("%s rendered frames %ld sample_rate %d",
5098 __func__, dsp_frames, out->sample_rate);
5099 *frames = dsp_frames;
5100 if (ret < 0)
5101 ret = -errno;
5102 if (-ENETRESET == ret) {
5103 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305104 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305105 ret = -EINVAL;
5106 } else
5107 ret = 0;
5108 /* this is the best we can do */
5109 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005110 } else {
5111 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005112 unsigned int avail;
5113 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5114 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5115 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5116 // This adjustment accounts for buffering after app processor.
5117 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005118 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005119 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005120
Weiyin Jiangd4633762018-03-16 12:05:03 +08005121 // Adjustment accounts for A2dp encoder latency with non offload usecases
5122 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5123 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5124 signed_frames -=
5125 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5126 }
5127
5128 // It would be unusual for this value to be negative, but check just in case ...
5129 if (signed_frames >= 0) {
5130 *frames = signed_frames;
5131 ret = 0;
5132 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005133 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305134 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305135 *frames = out->written;
5136 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05305137 if (is_offload_usecase(out->usecase))
5138 ret = -EINVAL;
5139 else
5140 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005141 }
5142 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005143 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005144 return ret;
5145}
5146
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005147static int out_set_callback(struct audio_stream_out *stream,
5148 stream_callback_t callback, void *cookie)
5149{
5150 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005151 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005152
5153 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005154 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005155 out->client_callback = callback;
5156 out->client_cookie = cookie;
5157 if (out->adsp_hdlr_stream_handle) {
5158 ret = audio_extn_adsp_hdlr_stream_set_callback(
5159 out->adsp_hdlr_stream_handle,
5160 callback,
5161 cookie);
5162 if (ret)
5163 ALOGW("%s:adsp hdlr callback registration failed %d",
5164 __func__, ret);
5165 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005166 pthread_mutex_unlock(&out->lock);
5167 return 0;
5168}
5169
5170static int out_pause(struct audio_stream_out* stream)
5171{
5172 struct stream_out *out = (struct stream_out *)stream;
5173 int status = -ENOSYS;
5174 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005175 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005176 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005177 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005178 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305179 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305180 status = compress_pause(out->compr);
5181
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005182 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005183
Mingming Yin21854652016-04-13 11:54:02 -07005184 if (audio_extn_passthru_is_active()) {
5185 ALOGV("offload use case, pause passthru");
5186 audio_extn_passthru_on_pause(out);
5187 }
5188
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305189 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005190 audio_extn_dts_notify_playback_state(out->usecase, 0,
5191 out->sample_rate, popcount(out->channel_mask),
5192 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005193 }
5194 pthread_mutex_unlock(&out->lock);
5195 }
5196 return status;
5197}
5198
5199static int out_resume(struct audio_stream_out* stream)
5200{
5201 struct stream_out *out = (struct stream_out *)stream;
5202 int status = -ENOSYS;
5203 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005204 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005205 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005206 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005207 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005208 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305209 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305210 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005211 }
5212 if (!status) {
5213 out->offload_state = OFFLOAD_STATE_PLAYING;
5214 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305215 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005216 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5217 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005218 }
5219 pthread_mutex_unlock(&out->lock);
5220 }
5221 return status;
5222}
5223
5224static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5225{
5226 struct stream_out *out = (struct stream_out *)stream;
5227 int status = -ENOSYS;
5228 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005229 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005230 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005231 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5232 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5233 else
5234 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5235 pthread_mutex_unlock(&out->lock);
5236 }
5237 return status;
5238}
5239
5240static int out_flush(struct audio_stream_out* stream)
5241{
5242 struct stream_out *out = (struct stream_out *)stream;
5243 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005244 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005245 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005246 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005247 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5248 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005249 } else {
5250 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5251 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005252 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005253 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005254 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005255 return 0;
5256 }
5257 return -ENOSYS;
5258}
5259
Haynes Mathew George16081042017-05-31 17:16:49 -07005260static int out_stop(const struct audio_stream_out* stream)
5261{
5262 struct stream_out *out = (struct stream_out *)stream;
5263 struct audio_device *adev = out->dev;
5264 int ret = -ENOSYS;
5265
5266 ALOGV("%s", __func__);
5267 pthread_mutex_lock(&adev->lock);
5268 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5269 out->playback_started && out->pcm != NULL) {
5270 pcm_stop(out->pcm);
5271 ret = stop_output_stream(out);
5272 out->playback_started = false;
5273 }
5274 pthread_mutex_unlock(&adev->lock);
5275 return ret;
5276}
5277
5278static int out_start(const struct audio_stream_out* stream)
5279{
5280 struct stream_out *out = (struct stream_out *)stream;
5281 struct audio_device *adev = out->dev;
5282 int ret = -ENOSYS;
5283
5284 ALOGV("%s", __func__);
5285 pthread_mutex_lock(&adev->lock);
5286 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5287 !out->playback_started && out->pcm != NULL) {
5288 ret = start_output_stream(out);
5289 if (ret == 0) {
5290 out->playback_started = true;
5291 }
5292 }
5293 pthread_mutex_unlock(&adev->lock);
5294 return ret;
5295}
5296
5297/*
5298 * Modify config->period_count based on min_size_frames
5299 */
5300static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5301{
5302 int periodCountRequested = (min_size_frames + config->period_size - 1)
5303 / config->period_size;
5304 int periodCount = MMAP_PERIOD_COUNT_MIN;
5305
5306 ALOGV("%s original config.period_size = %d config.period_count = %d",
5307 __func__, config->period_size, config->period_count);
5308
5309 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5310 periodCount *= 2;
5311 }
5312 config->period_count = periodCount;
5313
5314 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5315}
5316
5317static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5318 int32_t min_size_frames,
5319 struct audio_mmap_buffer_info *info)
5320{
5321 struct stream_out *out = (struct stream_out *)stream;
5322 struct audio_device *adev = out->dev;
5323 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005324 unsigned int offset1 = 0;
5325 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005326 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005327 uint32_t mmap_size;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005328 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005329
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005330 ALOGD("%s", __func__);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305331 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005332 pthread_mutex_lock(&adev->lock);
5333
Sharad Sangle90e613f2018-05-04 16:15:38 +05305334 if (CARD_STATUS_OFFLINE == out->card_status ||
5335 CARD_STATUS_OFFLINE == adev->card_status) {
5336 ALOGW("out->card_status or adev->card_status offline, try again");
5337 ret = -EIO;
5338 goto exit;
5339 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005340 if (info == NULL || min_size_frames == 0) {
5341 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5342 ret = -EINVAL;
5343 goto exit;
5344 }
5345 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5346 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5347 ret = -ENOSYS;
5348 goto exit;
5349 }
5350 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5351 if (out->pcm_device_id < 0) {
5352 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5353 __func__, out->pcm_device_id, out->usecase);
5354 ret = -EINVAL;
5355 goto exit;
5356 }
5357
5358 adjust_mmap_period_count(&out->config, min_size_frames);
5359
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005360 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005361 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5362 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5363 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305364 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
5365 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5366 out->card_status = CARD_STATUS_OFFLINE;
5367 adev->card_status = CARD_STATUS_OFFLINE;
5368 ret = -EIO;
5369 goto exit;
5370 }
5371
Haynes Mathew George16081042017-05-31 17:16:49 -07005372 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5373 step = "open";
5374 ret = -ENODEV;
5375 goto exit;
5376 }
5377 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5378 if (ret < 0) {
5379 step = "begin";
5380 goto exit;
5381 }
5382 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005383 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005384 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005385 ret = platform_get_mmap_data_fd(adev->platform,
5386 out->pcm_device_id, 0 /*playback*/,
5387 &info->shared_memory_fd,
5388 &mmap_size);
5389 if (ret < 0) {
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005390 // Fall back to non exclusive mode
5391 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5392 } else {
5393 if (mmap_size < buffer_size) {
5394 step = "mmap";
5395 goto exit;
5396 }
5397 // FIXME: indicate exclusive mode support by returning a negative buffer size
5398 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005399 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005400 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07005401
5402 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5403 if (ret < 0) {
5404 step = "commit";
5405 goto exit;
5406 }
5407
5408 out->standby = false;
5409 ret = 0;
5410
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005411 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005412 __func__, info->shared_memory_address, info->buffer_size_frames);
5413
5414exit:
5415 if (ret != 0) {
5416 if (out->pcm == NULL) {
5417 ALOGE("%s: %s - %d", __func__, step, ret);
5418 } else {
5419 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5420 pcm_close(out->pcm);
5421 out->pcm = NULL;
5422 }
5423 }
5424 pthread_mutex_unlock(&adev->lock);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305425 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005426 return ret;
5427}
5428
5429static int out_get_mmap_position(const struct audio_stream_out *stream,
5430 struct audio_mmap_position *position)
5431{
5432 struct stream_out *out = (struct stream_out *)stream;
5433 ALOGVV("%s", __func__);
5434 if (position == NULL) {
5435 return -EINVAL;
5436 }
5437 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005438 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005439 return -ENOSYS;
5440 }
5441 if (out->pcm == NULL) {
5442 return -ENOSYS;
5443 }
5444
5445 struct timespec ts = { 0, 0 };
5446 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5447 if (ret < 0) {
5448 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5449 return ret;
5450 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005451 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005452 return 0;
5453}
5454
5455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005456/** audio_stream_in implementation **/
5457static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5458{
5459 struct stream_in *in = (struct stream_in *)stream;
5460
5461 return in->config.rate;
5462}
5463
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005464static int in_set_sample_rate(struct audio_stream *stream __unused,
5465 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005466{
5467 return -ENOSYS;
5468}
5469
5470static size_t in_get_buffer_size(const struct audio_stream *stream)
5471{
5472 struct stream_in *in = (struct stream_in *)stream;
5473
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005474 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5475 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005476 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5477 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 -07005478 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5479 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305480 else if(audio_extn_cin_attached_usecase(in->usecase))
5481 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005482
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005483 return in->config.period_size * in->af_period_multiplier *
5484 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005485}
5486
5487static uint32_t in_get_channels(const struct audio_stream *stream)
5488{
5489 struct stream_in *in = (struct stream_in *)stream;
5490
5491 return in->channel_mask;
5492}
5493
5494static audio_format_t in_get_format(const struct audio_stream *stream)
5495{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005496 struct stream_in *in = (struct stream_in *)stream;
5497
5498 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005499}
5500
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005501static int in_set_format(struct audio_stream *stream __unused,
5502 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005503{
5504 return -ENOSYS;
5505}
5506
5507static int in_standby(struct audio_stream *stream)
5508{
5509 struct stream_in *in = (struct stream_in *)stream;
5510 struct audio_device *adev = in->dev;
5511 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305512 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5513 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005514 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305515
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005516 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005517 if (!in->standby && in->is_st_session) {
5518 ALOGD("%s: sound trigger pcm stop lab", __func__);
5519 audio_extn_sound_trigger_stop_lab(in);
5520 in->standby = 1;
5521 }
5522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005523 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005524 if (adev->adm_deregister_stream)
5525 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5526
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005527 pthread_mutex_lock(&adev->lock);
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05305528
5529 amplifier_input_stream_standby((struct audio_stream_in *) stream);
5530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005531 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005532 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005533 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005534 voice_extn_compress_voip_close_input_stream(stream);
5535 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005536 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5537 do_stop = in->capture_started;
5538 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005539 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305540 if (audio_extn_cin_attached_usecase(in->usecase))
5541 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005542 }
5543
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005544 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005545 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005546 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005547 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005548 in->pcm = NULL;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005549 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005550
5551 if (do_stop)
5552 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005553 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005554 }
5555 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005556 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005557 return status;
5558}
5559
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005560static int in_dump(const struct audio_stream *stream __unused,
5561 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005562{
5563 return 0;
5564}
5565
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305566static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5567{
5568 if (!stream || !parms)
5569 return;
5570
5571 struct stream_in *in = (struct stream_in *)stream;
5572 struct audio_device *adev = in->dev;
5573
5574 card_status_t status;
5575 int card;
5576 if (parse_snd_card_status(parms, &card, &status) < 0)
5577 return;
5578
5579 pthread_mutex_lock(&adev->lock);
5580 bool valid_cb = (card == adev->snd_card);
5581 pthread_mutex_unlock(&adev->lock);
5582
5583 if (!valid_cb)
5584 return;
5585
5586 lock_input_stream(in);
5587 if (in->card_status != status)
5588 in->card_status = status;
5589 pthread_mutex_unlock(&in->lock);
5590
5591 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5592 use_case_table[in->usecase],
5593 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5594
5595 // a better solution would be to report error back to AF and let
5596 // it put the stream to standby
5597 if (status == CARD_STATUS_OFFLINE)
5598 in_standby(&in->stream.common);
5599
5600 return;
5601}
5602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005603static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5604{
5605 struct stream_in *in = (struct stream_in *)stream;
5606 struct audio_device *adev = in->dev;
5607 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005608 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005609 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005610
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305611 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005612 parms = str_parms_create_str(kvpairs);
5613
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305614 if (!parms)
5615 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005616 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005617 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005618
5619 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5620 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005621 val = atoi(value);
5622 /* no audio source uses val == 0 */
5623 if ((in->source != val) && (val != 0)) {
5624 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005625 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5626 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5627 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005628 (in->config.rate == 8000 || in->config.rate == 16000 ||
5629 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005630 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005631 err = voice_extn_compress_voip_open_input_stream(in);
5632 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005633 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005634 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005635 }
5636 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005637 }
5638 }
5639
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005640 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5641 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005642 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005643 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5644
5645 // Workaround: If routing to an non existing usb device, fail gracefully
5646 // The routing request will otherwise block during 10 second
5647 int card;
5648 if (audio_is_usb_in_device(val) &&
5649 (card = get_alive_usb_card(parms)) >= 0) {
5650
5651 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5652 ret = -ENOSYS;
5653 } else {
5654
5655 in->device = val;
5656 /* If recording is in progress, change the tx device to new device */
5657 if (!in->standby && !in->is_st_session) {
5658 ALOGV("update input routing change");
5659 // inform adm before actual routing to prevent glitches.
5660 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005661 adev->adm_on_routing_change(adev->adm_data,
5662 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005663 ret = select_devices(adev, in->usecase);
5664 }
5665 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005666 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005667 }
5668 }
5669
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305670 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5671 if (err >= 0) {
5672 strlcpy(in->profile, value, sizeof(in->profile));
5673 ALOGV("updating stream profile with value '%s'", in->profile);
5674 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5675 &adev->streams_input_cfg_list,
5676 in->device, in->flags, in->format,
5677 in->sample_rate, in->bit_width,
5678 in->profile, &in->app_type_cfg);
5679 }
5680
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005681 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005682 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005683
5684 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305685error:
Eric Laurent994a6932013-07-17 11:51:42 -07005686 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005687 return ret;
5688}
5689
5690static char* in_get_parameters(const struct audio_stream *stream,
5691 const char *keys)
5692{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005693 struct stream_in *in = (struct stream_in *)stream;
5694 struct str_parms *query = str_parms_create_str(keys);
5695 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005696 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005697
5698 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005699 if (reply) {
5700 str_parms_destroy(reply);
5701 }
5702 if (query) {
5703 str_parms_destroy(query);
5704 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005705 ALOGE("in_get_parameters: failed to create query or reply");
5706 return NULL;
5707 }
5708
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005709 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005710
5711 voice_extn_in_get_parameters(in, query, reply);
5712
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005713 stream_get_parameter_channels(query, reply,
5714 &in->supported_channel_masks[0]);
5715 stream_get_parameter_formats(query, reply,
5716 &in->supported_formats[0]);
5717 stream_get_parameter_rates(query, reply,
5718 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005719 str = str_parms_to_str(reply);
5720 str_parms_destroy(query);
5721 str_parms_destroy(reply);
5722
5723 ALOGV("%s: exit: returns - %s", __func__, str);
5724 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005725}
5726
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005727static int in_set_gain(struct audio_stream_in *stream __unused,
5728 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005729{
5730 return 0;
5731}
5732
5733static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5734 size_t bytes)
5735{
5736 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305737
5738 if (in == NULL) {
5739 ALOGE("%s: stream_in ptr is NULL", __func__);
5740 return -EINVAL;
5741 }
5742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005743 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305744 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305745 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005746
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005747 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305748
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005749 if (in->is_st_session) {
5750 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5751 /* Read from sound trigger HAL */
5752 audio_extn_sound_trigger_read(in, buffer, bytes);
5753 pthread_mutex_unlock(&in->lock);
5754 return bytes;
5755 }
5756
Haynes Mathew George16081042017-05-31 17:16:49 -07005757 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5758 ret = -ENOSYS;
5759 goto exit;
5760 }
5761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005762 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005763 pthread_mutex_lock(&adev->lock);
5764 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5765 ret = voice_extn_compress_voip_start_input_stream(in);
5766 else
5767 ret = start_input_stream(in);
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05305768
5769 if (ret == 0)
5770 amplifier_input_stream_start(stream);
5771
5772
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005773 pthread_mutex_unlock(&adev->lock);
5774 if (ret != 0) {
5775 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005776 }
5777 in->standby = 0;
5778 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005779
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005780 // what's the duration requested by the client?
5781 long ns = 0;
5782
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305783 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005784 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5785 in->config.rate;
5786
5787 request_in_focus(in, ns);
5788 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005789
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305790 if (audio_extn_cin_attached_usecase(in->usecase)) {
5791 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5792 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305793 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005794 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305795 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005796 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005797 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005798 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005799 } else if (audio_extn_ffv_get_stream() == in) {
5800 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305801 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005802 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305803 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5804 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5805 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5806 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305807 ret = -EINVAL;
5808 goto exit;
5809 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305810 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305811 ret = -errno;
5812 }
5813 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305814 /* bytes read is always set to bytes for non compress usecases */
5815 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005816 }
5817
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005818 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005819
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005820 /*
5821 * Instead of writing zeroes here, we could trust the hardware
5822 * to always provide zeroes when muted.
5823 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305824 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5825 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005826 memset(buffer, 0, bytes);
5827
5828exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005829 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305830 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005831 pthread_mutex_unlock(&in->lock);
5832
5833 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305834 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305835 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305836 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305837 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305838 in->standby = true;
5839 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305840 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5841 bytes_read = bytes;
5842 memset(buffer, 0, bytes);
5843 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005844 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005845 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305846 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305847 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005848 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305849 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005850}
5851
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005852static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005853{
5854 return 0;
5855}
5856
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005857static int add_remove_audio_effect(const struct audio_stream *stream,
5858 effect_handle_t effect,
5859 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005860{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005861 struct stream_in *in = (struct stream_in *)stream;
5862 int status = 0;
5863 effect_descriptor_t desc;
5864
5865 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005866 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5867
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005868 if (status != 0)
5869 return status;
5870
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005871 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005872 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08005873 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5874 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005875 in->enable_aec != enable &&
5876 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5877 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005878 if (!in->standby) {
5879 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5880 select_devices(in->dev, in->usecase);
5881 }
5882
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005883 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005884 if (in->enable_ns != enable &&
5885 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5886 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005887 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08005888 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5889 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005890 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5891 select_devices(in->dev, in->usecase);
5892 } else
5893 select_devices(in->dev, in->usecase);
5894 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005895 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005896 pthread_mutex_unlock(&in->dev->lock);
5897 pthread_mutex_unlock(&in->lock);
5898
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005899 return 0;
5900}
5901
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005902static int in_add_audio_effect(const struct audio_stream *stream,
5903 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005904{
Eric Laurent994a6932013-07-17 11:51:42 -07005905 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005906 return add_remove_audio_effect(stream, effect, true);
5907}
5908
5909static int in_remove_audio_effect(const struct audio_stream *stream,
5910 effect_handle_t effect)
5911{
Eric Laurent994a6932013-07-17 11:51:42 -07005912 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005913 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005914}
5915
Haynes Mathew George16081042017-05-31 17:16:49 -07005916static int in_stop(const struct audio_stream_in* stream)
5917{
5918 struct stream_in *in = (struct stream_in *)stream;
5919 struct audio_device *adev = in->dev;
5920
5921 int ret = -ENOSYS;
5922 ALOGV("%s", __func__);
5923 pthread_mutex_lock(&adev->lock);
5924 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5925 in->capture_started && in->pcm != NULL) {
5926 pcm_stop(in->pcm);
5927 ret = stop_input_stream(in);
5928 in->capture_started = false;
5929 }
5930 pthread_mutex_unlock(&adev->lock);
5931 return ret;
5932}
5933
5934static int in_start(const struct audio_stream_in* stream)
5935{
5936 struct stream_in *in = (struct stream_in *)stream;
5937 struct audio_device *adev = in->dev;
5938 int ret = -ENOSYS;
5939
5940 ALOGV("%s in %p", __func__, in);
5941 pthread_mutex_lock(&adev->lock);
5942 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5943 !in->capture_started && in->pcm != NULL) {
5944 if (!in->capture_started) {
5945 ret = start_input_stream(in);
5946 if (ret == 0) {
5947 in->capture_started = true;
5948 }
5949 }
5950 }
5951 pthread_mutex_unlock(&adev->lock);
5952 return ret;
5953}
5954
5955static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5956 int32_t min_size_frames,
5957 struct audio_mmap_buffer_info *info)
5958{
5959 struct stream_in *in = (struct stream_in *)stream;
5960 struct audio_device *adev = in->dev;
5961 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005962 unsigned int offset1 = 0;
5963 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005964 const char *step = "";
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005965 uint32_t mmap_size = 0;
5966 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005967
5968 pthread_mutex_lock(&adev->lock);
5969 ALOGV("%s in %p", __func__, in);
5970
Sharad Sangle90e613f2018-05-04 16:15:38 +05305971 if (CARD_STATUS_OFFLINE == in->card_status||
5972 CARD_STATUS_OFFLINE == adev->card_status) {
5973 ALOGW("in->card_status or adev->card_status offline, try again");
5974 ret = -EIO;
5975 goto exit;
5976 }
5977
Haynes Mathew George16081042017-05-31 17:16:49 -07005978 if (info == NULL || min_size_frames == 0) {
5979 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5980 ret = -EINVAL;
5981 goto exit;
5982 }
5983 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5984 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5985 ALOGV("%s in %p", __func__, in);
5986 ret = -ENOSYS;
5987 goto exit;
5988 }
5989 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5990 if (in->pcm_device_id < 0) {
5991 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5992 __func__, in->pcm_device_id, in->usecase);
5993 ret = -EINVAL;
5994 goto exit;
5995 }
5996
5997 adjust_mmap_period_count(&in->config, min_size_frames);
5998
5999 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
6000 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
6001 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6002 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Sharad Sangle90e613f2018-05-04 16:15:38 +05306003 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
6004 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6005 in->card_status = CARD_STATUS_OFFLINE;
6006 adev->card_status = CARD_STATUS_OFFLINE;
6007 ret = -EIO;
6008 goto exit;
6009 }
6010
Haynes Mathew George16081042017-05-31 17:16:49 -07006011 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6012 step = "open";
6013 ret = -ENODEV;
6014 goto exit;
6015 }
6016
6017 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6018 if (ret < 0) {
6019 step = "begin";
6020 goto exit;
6021 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006022
Arun Mirpuriebe78a72018-10-04 18:23:46 -07006023 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
6024 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
6025 info->burst_size_frames = in->config.period_size;
6026 ret = platform_get_mmap_data_fd(adev->platform,
6027 in->pcm_device_id, 1 /*capture*/,
6028 &info->shared_memory_fd,
6029 &mmap_size);
6030 if (ret < 0) {
6031 // Fall back to non exclusive mode
6032 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6033 } else {
6034 if (mmap_size < buffer_size) {
6035 step = "mmap";
6036 goto exit;
6037 }
6038 // FIXME: indicate exclusive mode support by returning a negative buffer size
6039 info->buffer_size_frames *= -1;
6040 }
6041
6042 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006043
6044 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6045 if (ret < 0) {
6046 step = "commit";
6047 goto exit;
6048 }
6049
6050 in->standby = false;
6051 ret = 0;
6052
6053 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6054 __func__, info->shared_memory_address, info->buffer_size_frames);
6055
6056exit:
6057 if (ret != 0) {
6058 if (in->pcm == NULL) {
6059 ALOGE("%s: %s - %d", __func__, step, ret);
6060 } else {
6061 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6062 pcm_close(in->pcm);
6063 in->pcm = NULL;
6064 }
6065 }
6066 pthread_mutex_unlock(&adev->lock);
6067 return ret;
6068}
6069
6070static int in_get_mmap_position(const struct audio_stream_in *stream,
6071 struct audio_mmap_position *position)
6072{
6073 struct stream_in *in = (struct stream_in *)stream;
6074 ALOGVV("%s", __func__);
6075 if (position == NULL) {
6076 return -EINVAL;
6077 }
6078 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6079 return -ENOSYS;
6080 }
6081 if (in->pcm == NULL) {
6082 return -ENOSYS;
6083 }
6084 struct timespec ts = { 0, 0 };
6085 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6086 if (ret < 0) {
6087 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6088 return ret;
6089 }
Naresh Tannirua15d7e92018-11-02 09:49:44 +05306090 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07006091 return 0;
6092}
6093
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306094static int in_get_active_microphones(const struct audio_stream_in *stream,
6095 struct audio_microphone_characteristic_t *mic_array,
6096 size_t *mic_count) {
6097 struct stream_in *in = (struct stream_in *)stream;
6098 struct audio_device *adev = in->dev;
6099 ALOGVV("%s", __func__);
6100
6101 lock_input_stream(in);
6102 pthread_mutex_lock(&adev->lock);
6103 int ret = platform_get_active_microphones(adev->platform,
6104 audio_channel_count_from_in_mask(in->channel_mask),
6105 in->usecase, mic_array, mic_count);
6106 pthread_mutex_unlock(&adev->lock);
6107 pthread_mutex_unlock(&in->lock);
6108
6109 return ret;
6110}
6111
6112static int adev_get_microphones(const struct audio_hw_device *dev,
6113 struct audio_microphone_characteristic_t *mic_array,
6114 size_t *mic_count) {
6115 struct audio_device *adev = (struct audio_device *)dev;
6116 ALOGVV("%s", __func__);
6117
6118 pthread_mutex_lock(&adev->lock);
6119 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6120 pthread_mutex_unlock(&adev->lock);
6121
6122 return ret;
6123}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306124int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006125 audio_io_handle_t handle,
6126 audio_devices_t devices,
6127 audio_output_flags_t flags,
6128 struct audio_config *config,
6129 struct audio_stream_out **stream_out,
6130 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006131{
6132 struct audio_device *adev = (struct audio_device *)dev;
6133 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306134 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006135 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006136 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306137 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006138 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6139 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6140 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6141 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006142
kunleizdff872d2018-08-20 14:40:33 +08006143 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006144 is_usb_dev = false;
6145 devices = AUDIO_DEVICE_OUT_SPEAKER;
6146 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6147 __func__, devices);
6148 }
6149
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006150 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306151
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006152 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6153
Mingming Yin3a941d42016-02-17 18:08:05 -08006154 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6155 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306156 devices, flags, &out->stream);
6157
6158
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006159 if (!out) {
6160 return -ENOMEM;
6161 }
6162
Haynes Mathew George204045b2015-02-25 20:32:03 -08006163 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006164 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306165 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006166 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006167 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6168
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006169 if (devices == AUDIO_DEVICE_NONE)
6170 devices = AUDIO_DEVICE_OUT_SPEAKER;
6171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006172 out->flags = flags;
6173 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006174 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006175 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006176 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306177 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306178 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6179 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6180 else
6181 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006182 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006183 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006184 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306185 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306186 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306187 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006188 out->hal_output_suspend_supported = 0;
6189 out->dynamic_pm_qos_config_supported = 0;
Surendar Karka5a18a7a2018-04-26 11:28:38 +05306190 out->set_dual_mono = false;
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05306191 out->prev_card_status_offline = false;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05306192 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006193
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306194 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306195 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006196 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6197
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006198 if (audio_is_linear_pcm(out->format) &&
6199 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
6200 pthread_mutex_lock(&adev->lock);
6201 if (is_hdmi) {
6202 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6203 ret = read_hdmi_sink_caps(out);
6204 } else if (is_usb_dev) {
6205 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6206 &config->format,
6207 &out->supported_formats[0],
6208 MAX_SUPPORTED_FORMATS,
6209 &config->channel_mask,
6210 &out->supported_channel_masks[0],
6211 MAX_SUPPORTED_CHANNEL_MASKS,
6212 &config->sample_rate,
6213 &out->supported_sample_rates[0],
6214 MAX_SUPPORTED_SAMPLE_RATES);
6215 ALOGV("plugged dev USB ret %d", ret);
6216 } else {
6217 ret = -1;
6218 }
6219 pthread_mutex_unlock(&adev->lock);
6220 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006221 if (ret == -ENOSYS) {
6222 /* ignore and go with default */
6223 ret = 0;
6224 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006225 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006226 goto error_open;
6227 }
6228 }
6229 }
6230
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006231 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07006232#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006233 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6234 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6235 out->sample_rate == 32000 || out->sample_rate == 48000)) {
6236 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
6237 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
6238 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
6239
6240 out->config = default_pcm_config_voip_copp;
6241 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6242 out->config.rate = out->sample_rate;
6243
6244#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05306245 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006246 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08006247 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006248 ret = voice_extn_compress_voip_open_output_stream(out);
6249 if (ret != 0) {
6250 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6251 __func__, ret);
6252 goto error_open;
6253 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006254#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006255 } else if (audio_is_linear_pcm(out->format) &&
6256 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6257 out->channel_mask = config->channel_mask;
6258 out->sample_rate = config->sample_rate;
6259 out->format = config->format;
6260 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6261 // does this change?
6262 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6263 out->config.rate = config->sample_rate;
6264 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6265 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6266 audio_bytes_per_sample(config->format));
6267 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006268 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306269 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306270 pthread_mutex_lock(&adev->lock);
6271 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6272 pthread_mutex_unlock(&adev->lock);
6273
6274 // reject offload during card offline to allow
6275 // fallback to s/w paths
6276 if (offline) {
6277 ret = -ENODEV;
6278 goto error_open;
6279 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006280
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006281 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6282 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6283 ALOGE("%s: Unsupported Offload information", __func__);
6284 ret = -EINVAL;
6285 goto error_open;
6286 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006287
Atul Khare3fa6e542017-08-09 00:56:17 +05306288 if (config->offload_info.format == 0)
6289 config->offload_info.format = config->format;
6290 if (config->offload_info.sample_rate == 0)
6291 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006292
Mingming Yin90310102013-11-13 16:57:00 -08006293 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306294 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006295 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006296 ret = -EINVAL;
6297 goto error_open;
6298 }
6299
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006300 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6301 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6302 (audio_extn_passthru_is_passthrough_stream(out)) &&
6303 !((config->sample_rate == 48000) ||
6304 (config->sample_rate == 96000) ||
6305 (config->sample_rate == 192000))) {
6306 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6307 __func__, config->sample_rate, config->offload_info.format);
6308 ret = -EINVAL;
6309 goto error_open;
6310 }
6311
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006312 out->compr_config.codec = (struct snd_codec *)
6313 calloc(1, sizeof(struct snd_codec));
6314
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006315 if (!out->compr_config.codec) {
6316 ret = -ENOMEM;
6317 goto error_open;
6318 }
6319
Dhananjay Kumarac341582017-02-23 23:42:25 +05306320 out->stream.pause = out_pause;
6321 out->stream.resume = out_resume;
6322 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306323 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306324 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006325 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306326 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006327 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306328 } else {
6329 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6330 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006331 }
vivek mehta446c3962015-09-14 10:57:35 -07006332
6333 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006334 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6335 config->format == 0 && config->sample_rate == 0 &&
6336 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006337 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006338 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6339 } else {
6340 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6341 ret = -EEXIST;
6342 goto error_open;
6343 }
vivek mehta446c3962015-09-14 10:57:35 -07006344 }
6345
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006346 if (config->offload_info.channel_mask)
6347 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006348 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006349 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006350 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006351 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306352 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006353 ret = -EINVAL;
6354 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006355 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006356
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006357 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006358 out->sample_rate = config->offload_info.sample_rate;
6359
Mingming Yin3ee55c62014-08-04 14:23:35 -07006360 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006361
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306362 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306363 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306364 audio_extn_dolby_send_ddp_endp_params(adev);
6365 audio_extn_dolby_set_dmid(adev);
6366 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006367
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006368 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006369 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006370 out->compr_config.codec->bit_rate =
6371 config->offload_info.bit_rate;
6372 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306373 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006374 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306375 /* Update bit width only for non passthrough usecases.
6376 * For passthrough usecases, the output will always be opened @16 bit
6377 */
6378 if (!audio_extn_passthru_is_passthrough_stream(out))
6379 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306380
6381 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6382 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6383 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6384
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006385 /*TODO: Do we need to change it for passthrough */
6386 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006387
Manish Dewangana6fc5442015-08-24 20:30:31 +05306388 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6389 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306390 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306391 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306392 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6393 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306394
6395 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6396 AUDIO_FORMAT_PCM) {
6397
6398 /*Based on platform support, configure appropriate alsa format for corresponding
6399 *hal input format.
6400 */
6401 out->compr_config.codec->format = hal_format_to_alsa(
6402 config->offload_info.format);
6403
Ashish Jain83a6cc22016-06-28 14:34:17 +05306404 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306405 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306406 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306407
Dhananjay Kumarac341582017-02-23 23:42:25 +05306408 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306409 *hal input format and alsa format might differ based on platform support.
6410 */
6411 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306412 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306413
6414 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6415
6416 /* Check if alsa session is configured with the same format as HAL input format,
6417 * if not then derive correct fragment size needed to accomodate the
6418 * conversion of HAL input format to alsa format.
6419 */
6420 audio_extn_utils_update_direct_pcm_fragment_size(out);
6421
6422 /*if hal input and output fragment size is different this indicates HAL input format is
6423 *not same as the alsa format
6424 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306425 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306426 /*Allocate a buffer to convert input data to the alsa configured format.
6427 *size of convert buffer is equal to the size required to hold one fragment size
6428 *worth of pcm data, this is because flinger does not write more than fragment_size
6429 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306430 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6431 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306432 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6433 ret = -ENOMEM;
6434 goto error_open;
6435 }
6436 }
6437 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6438 out->compr_config.fragment_size =
6439 audio_extn_passthru_get_buffer_size(&config->offload_info);
6440 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6441 } else {
6442 out->compr_config.fragment_size =
6443 platform_get_compress_offload_buffer_size(&config->offload_info);
6444 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6445 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006446
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306447 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6448 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6449 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006450 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306451 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006452
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306453 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6454 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6455 }
6456
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006457 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6458 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006459
Manish Dewangan69426c82017-01-30 17:35:36 +05306460 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6461 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6462 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6463 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6464 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6465 } else {
6466 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6467 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006468
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306469 memset(&out->channel_map_param, 0,
6470 sizeof(struct audio_out_channel_map_param));
6471
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006472 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306473 out->send_next_track_params = false;
6474 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006475 out->offload_state = OFFLOAD_STATE_IDLE;
6476 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006477 out->writeAt.tv_sec = 0;
6478 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006479
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006480 audio_extn_dts_create_state_notifier_node(out->usecase);
6481
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006482 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6483 __func__, config->offload_info.version,
6484 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306485
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306486 /* Check if DSD audio format is supported in codec
6487 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306488 */
6489
6490 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306491 (!platform_check_codec_dsd_support(adev->platform) ||
6492 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306493 ret = -EINVAL;
6494 goto error_open;
6495 }
6496
Ashish Jain5106d362016-05-11 19:23:33 +05306497 /* Disable gapless if any of the following is true
6498 * passthrough playback
6499 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306500 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306501 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306502 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306503 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006504 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306505 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306506 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306507 check_and_set_gapless_mode(adev, false);
6508 } else
6509 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006510
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306511 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006512 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6513 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306514 if (config->format == AUDIO_FORMAT_DSD) {
6515 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6516 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6517 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006518
6519 create_offload_callback_thread(out);
6520
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006521 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006522 switch (config->sample_rate) {
6523 case 0:
6524 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6525 break;
6526 case 8000:
6527 case 16000:
6528 case 48000:
6529 out->sample_rate = config->sample_rate;
6530 break;
6531 default:
6532 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
6533 config->sample_rate);
6534 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6535 ret = -EINVAL;
6536 goto error_open;
6537 }
6538 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6539 switch (config->channel_mask) {
6540 case AUDIO_CHANNEL_NONE:
6541 case AUDIO_CHANNEL_OUT_STEREO:
6542 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6543 break;
6544 default:
6545 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
6546 config->channel_mask);
6547 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6548 ret = -EINVAL;
6549 goto error_open;
6550 }
6551 switch (config->format) {
6552 case AUDIO_FORMAT_DEFAULT:
6553 case AUDIO_FORMAT_PCM_16_BIT:
6554 out->format = AUDIO_FORMAT_PCM_16_BIT;
6555 break;
6556 default:
6557 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
6558 config->format);
6559 config->format = AUDIO_FORMAT_PCM_16_BIT;
6560 ret = -EINVAL;
6561 goto error_open;
6562 }
6563
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306564 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006565 if (ret != 0) {
6566 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006567 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006568 goto error_open;
6569 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006570 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006571 if (config->sample_rate == 0)
6572 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6573 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6574 config->sample_rate != 8000) {
6575 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6576 ret = -EINVAL;
6577 goto error_open;
6578 }
6579 out->sample_rate = config->sample_rate;
6580 out->config.rate = config->sample_rate;
6581 if (config->format == AUDIO_FORMAT_DEFAULT)
6582 config->format = AUDIO_FORMAT_PCM_16_BIT;
6583 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6584 config->format = AUDIO_FORMAT_PCM_16_BIT;
6585 ret = -EINVAL;
6586 goto error_open;
6587 }
6588 out->format = config->format;
6589 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
6590 out->config = pcm_config_afe_proxy_playback;
6591 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006592 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05306593 unsigned int channels = 0;
6594 /*Update config params to default if not set by the caller*/
6595 if (config->sample_rate == 0)
6596 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6597 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6598 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6599 if (config->format == AUDIO_FORMAT_DEFAULT)
6600 config->format = AUDIO_FORMAT_PCM_16_BIT;
6601
6602 channels = audio_channel_count_from_out_mask(out->channel_mask);
6603
Varun Balaraje49253e2017-07-06 19:48:56 +05306604 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6605 out->usecase = get_interactive_usecase(adev);
6606 out->config = pcm_config_low_latency;
6607 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306608 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006609 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6610 out->flags);
6611 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006612 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6613 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6614 out->config = pcm_config_mmap_playback;
6615 out->stream.start = out_start;
6616 out->stream.stop = out_stop;
6617 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6618 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306619 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6620 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006621 out->hal_output_suspend_supported =
6622 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6623 out->dynamic_pm_qos_config_supported =
6624 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6625 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006626 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6627 } else {
6628 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6629 //the mixer path will be a string similar to "low-latency-playback resume"
6630 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6631 strlcat(out->pm_qos_mixer_path,
6632 " resume", MAX_MIXER_PATH_LEN);
6633 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6634 out->pm_qos_mixer_path);
6635 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306636 out->config = pcm_config_low_latency;
6637 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6638 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6639 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306640 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6641 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6642 if (out->config.period_size <= 0) {
6643 ALOGE("Invalid configuration period size is not valid");
6644 ret = -EINVAL;
6645 goto error_open;
6646 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306647 } else {
6648 /* primary path is the default path selected if no other outputs are available/suitable */
6649 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6650 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6651 }
6652 out->hal_ip_format = format = out->format;
6653 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6654 out->hal_op_format = pcm_format_to_hal(out->config.format);
6655 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6656 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006657 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306658 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306659 if (out->hal_ip_format != out->hal_op_format) {
6660 uint32_t buffer_size = out->config.period_size *
6661 format_to_bitwidth_table[out->hal_op_format] *
6662 out->config.channels;
6663 out->convert_buffer = calloc(1, buffer_size);
6664 if (out->convert_buffer == NULL){
6665 ALOGE("Allocation failed for convert buffer for size %d",
6666 out->compr_config.fragment_size);
6667 ret = -ENOMEM;
6668 goto error_open;
6669 }
6670 ALOGD("Convert buffer allocated of size %d", buffer_size);
6671 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006672 }
6673
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006674 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6675 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306676
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006677 /* TODO remove this hardcoding and check why width is zero*/
6678 if (out->bit_width == 0)
6679 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306680 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006681 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006682 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306683 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306684 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006685 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6686 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6687 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006688 if(adev->primary_output == NULL)
6689 adev->primary_output = out;
6690 else {
6691 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006692 ret = -EEXIST;
6693 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006694 }
6695 }
6696
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006697 /* Check if this usecase is already existing */
6698 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006699 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6700 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006701 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006702 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006703 ret = -EEXIST;
6704 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006705 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006706
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006707 pthread_mutex_unlock(&adev->lock);
6708
6709 out->stream.common.get_sample_rate = out_get_sample_rate;
6710 out->stream.common.set_sample_rate = out_set_sample_rate;
6711 out->stream.common.get_buffer_size = out_get_buffer_size;
6712 out->stream.common.get_channels = out_get_channels;
6713 out->stream.common.get_format = out_get_format;
6714 out->stream.common.set_format = out_set_format;
6715 out->stream.common.standby = out_standby;
6716 out->stream.common.dump = out_dump;
6717 out->stream.common.set_parameters = out_set_parameters;
6718 out->stream.common.get_parameters = out_get_parameters;
6719 out->stream.common.add_audio_effect = out_add_audio_effect;
6720 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6721 out->stream.get_latency = out_get_latency;
6722 out->stream.set_volume = out_set_volume;
6723 out->stream.write = out_write;
6724 out->stream.get_render_position = out_get_render_position;
6725 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006726 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006727
Haynes Mathew George16081042017-05-31 17:16:49 -07006728 if (out->realtime)
6729 out->af_period_multiplier = af_period_multiplier;
6730 else
6731 out->af_period_multiplier = 1;
6732
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006733 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006734 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006735 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006736
6737 config->format = out->stream.common.get_format(&out->stream.common);
6738 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6739 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05306740 register_format(out->format, out->supported_formats);
6741 register_channel_mask(out->channel_mask, out->supported_channel_masks);
6742 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006743
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306744 /*
6745 By locking output stream before registering, we allow the callback
6746 to update stream's state only after stream's initial state is set to
6747 adev state.
6748 */
6749 lock_output_stream(out);
6750 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6751 pthread_mutex_lock(&adev->lock);
6752 out->card_status = adev->card_status;
6753 pthread_mutex_unlock(&adev->lock);
6754 pthread_mutex_unlock(&out->lock);
6755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006756 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306757 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006758 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006759
6760 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6761 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6762 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006763 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306764 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006765 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006766 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306767 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006768 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6769 out->usecase, PCM_PLAYBACK);
6770 hdlr_stream_cfg.flags = out->flags;
6771 hdlr_stream_cfg.type = PCM_PLAYBACK;
6772 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6773 &hdlr_stream_cfg);
6774 if (ret) {
6775 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6776 out->adsp_hdlr_stream_handle = NULL;
6777 }
6778 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306779 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006780 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006781 if (ret < 0) {
6782 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6783 out->ip_hdlr_handle = NULL;
6784 }
6785 }
Eric Laurent994a6932013-07-17 11:51:42 -07006786 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006787 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006788
6789error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306790 if (out->convert_buffer)
6791 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006792 free(out);
6793 *stream_out = NULL;
6794 ALOGD("%s: exit: ret %d", __func__, ret);
6795 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006796}
6797
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306798void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006799 struct audio_stream_out *stream)
6800{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006801 struct stream_out *out = (struct stream_out *)stream;
6802 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006803 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006804
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006805 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306806
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306807 // must deregister from sndmonitor first to prevent races
6808 // between the callback and close_stream
6809 audio_extn_snd_mon_unregister_listener(out);
6810
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006811 /* close adsp hdrl session before standby */
6812 if (out->adsp_hdlr_stream_handle) {
6813 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6814 if (ret)
6815 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6816 out->adsp_hdlr_stream_handle = NULL;
6817 }
6818
Manish Dewangan21a850a2017-08-14 12:03:55 +05306819 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006820 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6821 out->ip_hdlr_handle = NULL;
6822 }
6823
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006824 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306825 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006826 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306827 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306828 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006829 if(ret != 0)
6830 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6831 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006832 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006833 out_standby(&stream->common);
6834
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006835 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006836 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006837 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006838 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006839 if (out->compr_config.codec != NULL)
6840 free(out->compr_config.codec);
6841 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006842
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306843 out->a2dp_compress_mute = false;
6844
Varun Balaraje49253e2017-07-06 19:48:56 +05306845 if (is_interactive_usecase(out->usecase))
6846 free_interactive_usecase(adev, out->usecase);
6847
Ashish Jain83a6cc22016-06-28 14:34:17 +05306848 if (out->convert_buffer != NULL) {
6849 free(out->convert_buffer);
6850 out->convert_buffer = NULL;
6851 }
6852
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006853 if (adev->voice_tx_output == out)
6854 adev->voice_tx_output = NULL;
6855
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306856 if (adev->primary_output == out)
6857 adev->primary_output = NULL;
6858
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006859 pthread_cond_destroy(&out->cond);
6860 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006861 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006862 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006863}
6864
6865static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6866{
6867 struct audio_device *adev = (struct audio_device *)dev;
6868 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006869 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006870 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006871 int ret;
6872 int status = 0;
Zhou Songa32012a2019-05-21 18:08:51 +08006873 struct listnode *node;
6874 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006875
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006876 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006877 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006878
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306879 if (!parms)
6880 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306881
Zhou Songa32012a2019-05-21 18:08:51 +08006882 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306883 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6884 if (ret >= 0) {
6885 /* When set to false, HAL should disable EC and NS */
Zhou Songa32012a2019-05-21 18:08:51 +08006886 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306887 adev->bt_sco_on = true;
Zhou Songa32012a2019-05-21 18:08:51 +08006888 } else {
6889 ALOGD("route device to handset/mic when sco is off");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306890 adev->bt_sco_on = false;
Zhou Songa32012a2019-05-21 18:08:51 +08006891 list_for_each(node, &adev->usecase_list) {
6892 usecase = node_to_item(node, struct audio_usecase, list);
6893 if ((usecase->type == PCM_PLAYBACK) && usecase->stream.out &&
6894 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_SCO))
6895 usecase->stream.out->devices = AUDIO_DEVICE_OUT_EARPIECE;
6896 else if ((usecase->type == PCM_CAPTURE) && usecase->stream.in &&
6897 (usecase->stream.in->device & AUDIO_DEVICE_IN_ALL_SCO))
6898 usecase->stream.in->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
6899 else
6900 continue;
6901 select_devices(adev, usecase->id);
6902 }
6903 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306904 }
6905
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006906 status = voice_set_parameters(adev, parms);
6907 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006908 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006909
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006910 status = platform_set_parameters(adev->platform, parms);
6911 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006912 goto done;
6913
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006914 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6915 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006916 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006917 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6918 adev->bluetooth_nrec = true;
6919 else
6920 adev->bluetooth_nrec = false;
6921 }
6922
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006923 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6924 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006925 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6926 adev->screen_off = false;
6927 else
6928 adev->screen_off = true;
6929 }
6930
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006931 ret = str_parms_get_int(parms, "rotation", &val);
6932 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006933 bool reverse_speakers = false;
6934 switch(val) {
6935 // FIXME: note that the code below assumes that the speakers are in the correct placement
6936 // relative to the user when the device is rotated 90deg from its default rotation. This
6937 // assumption is device-specific, not platform-specific like this code.
6938 case 270:
6939 reverse_speakers = true;
6940 break;
6941 case 0:
6942 case 90:
6943 case 180:
6944 break;
6945 default:
6946 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006947 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006948 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006949 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006950 // check and set swap
6951 // - check if orientation changed and speaker active
6952 // - set rotation and cache the rotation value
6953 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006954 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006955 }
6956
Mingming Yin514a8bc2014-07-29 15:22:21 -07006957 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6958 if (ret >= 0) {
6959 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6960 adev->bt_wb_speech_enabled = true;
6961 else
6962 adev->bt_wb_speech_enabled = false;
6963 }
6964
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006965 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6966 if (ret >= 0) {
6967 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306968 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08006969 if (audio_is_output_device(val) &&
6970 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006971 ALOGV("cache new ext disp type and edid");
6972 ret = platform_get_ext_disp_type(adev->platform);
6973 if (ret < 0) {
6974 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05306975 } else {
6976 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006977 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306978 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07006979 /*
6980 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6981 * Per AudioPolicyManager, USB device is higher priority than WFD.
6982 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6983 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6984 * starting voice call on USB
6985 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006986 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306987 if (ret >= 0)
6988 audio_extn_usb_add_device(device, atoi(value));
6989
Zhou Song6f862822017-11-06 17:27:57 +08006990 if (!audio_extn_usb_is_tunnel_supported()) {
6991 ALOGV("detected USB connect .. disable proxy");
6992 adev->allow_afe_proxy_usage = false;
6993 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006994 }
6995 }
6996
6997 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6998 if (ret >= 0) {
6999 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307000 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07007001 /*
7002 * The HDMI / Displayport disconnect handling has been moved to
7003 * audio extension to ensure that its parameters are not
7004 * invalidated prior to updating sysfs of the disconnect event
7005 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
7006 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307007 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007008 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307009 if (ret >= 0)
7010 audio_extn_usb_remove_device(device, atoi(value));
7011
Zhou Song6f862822017-11-06 17:27:57 +08007012 if (!audio_extn_usb_is_tunnel_supported()) {
7013 ALOGV("detected USB disconnect .. enable proxy");
7014 adev->allow_afe_proxy_usage = true;
7015 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007016 }
7017 }
7018
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307019 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
7020 if (ret >= 0) {
7021 struct audio_usecase *usecase;
7022 struct listnode *node;
7023 list_for_each(node, &adev->usecase_list) {
7024 usecase = node_to_item(node, struct audio_usecase, list);
7025 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07007026 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307027 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08007028
7029 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307030 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08007031 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307032 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307033 //force device switch to re configure encoder
7034 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307035 audio_extn_a2dp_set_handoff_mode(false);
7036 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307037 break;
7038 }
7039 }
7040 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007041
7042 //handle vr audio setparam
7043 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7044 value, sizeof(value));
7045 if (ret >= 0) {
7046 ALOGI("Setting vr mode to be %s", value);
7047 if (!strncmp(value, "true", 4)) {
7048 adev->vr_audio_mode_enabled = true;
7049 ALOGI("Setting vr mode to true");
7050 } else if (!strncmp(value, "false", 5)) {
7051 adev->vr_audio_mode_enabled = false;
7052 ALOGI("Setting vr mode to false");
7053 } else {
7054 ALOGI("wrong vr mode set");
7055 }
7056 }
7057
Balázs Triszka6e101332018-02-26 22:11:10 +01007058 ret = str_parms_get_int(parms, "ultrasound_enable", &val);
7059 if (ret >= 0) {
7060 if (val == 1) {
7061 us_start();
7062 } else {
7063 us_stop();
7064 }
7065 }
7066
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05307067 amplifier_set_parameters(parms);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307068 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007069done:
7070 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007071 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307072error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007073 ALOGV("%s: exit with code(%d)", __func__, status);
7074 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007075}
7076
7077static char* adev_get_parameters(const struct audio_hw_device *dev,
7078 const char *keys)
7079{
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05307080 ALOGD("%s:%s", __func__, keys);
7081
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007082 struct audio_device *adev = (struct audio_device *)dev;
7083 struct str_parms *reply = str_parms_create();
7084 struct str_parms *query = str_parms_create_str(keys);
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05307085
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007086 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05307087 char value[256] = {0};
7088 int ret = 0;
7089
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007090 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007091 if (reply) {
7092 str_parms_destroy(reply);
7093 }
7094 if (query) {
7095 str_parms_destroy(query);
7096 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007097 ALOGE("adev_get_parameters: failed to create query or reply");
7098 return NULL;
7099 }
7100
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007101 //handle vr audio getparam
7102
7103 ret = str_parms_get_str(query,
7104 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7105 value, sizeof(value));
7106
7107 if (ret >= 0) {
7108 bool vr_audio_enabled = false;
7109 pthread_mutex_lock(&adev->lock);
7110 vr_audio_enabled = adev->vr_audio_mode_enabled;
7111 pthread_mutex_unlock(&adev->lock);
7112
7113 ALOGI("getting vr mode to %d", vr_audio_enabled);
7114
7115 if (vr_audio_enabled) {
7116 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7117 "true");
7118 goto exit;
7119 } else {
7120 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7121 "false");
7122 goto exit;
7123 }
7124 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007125
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007126 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007127 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08007128 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007129 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05307130 pthread_mutex_unlock(&adev->lock);
7131
Naresh Tannirud7205b62014-06-20 02:54:48 +05307132exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007133 str = str_parms_to_str(reply);
7134 str_parms_destroy(query);
7135 str_parms_destroy(reply);
7136
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05307137 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007138 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007139}
7140
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007141static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007142{
7143 return 0;
7144}
7145
7146static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
7147{
Haynes Mathew George5191a852013-09-11 14:19:36 -07007148 int ret;
7149 struct audio_device *adev = (struct audio_device *)dev;
7150 pthread_mutex_lock(&adev->lock);
7151 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07007152 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07007153 pthread_mutex_unlock(&adev->lock);
7154 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007155}
7156
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007157static int adev_set_master_volume(struct audio_hw_device *dev __unused,
7158 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007159{
7160 return -ENOSYS;
7161}
7162
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007163static int adev_get_master_volume(struct audio_hw_device *dev __unused,
7164 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007165{
7166 return -ENOSYS;
7167}
7168
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007169static int adev_set_master_mute(struct audio_hw_device *dev __unused,
7170 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007171{
7172 return -ENOSYS;
7173}
7174
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007175static int adev_get_master_mute(struct audio_hw_device *dev __unused,
7176 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007177{
7178 return -ENOSYS;
7179}
7180
7181static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
7182{
7183 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07007184 struct listnode *node;
7185 struct audio_usecase *usecase = NULL;
7186 int ret = 0;
kunleiz60c17e72017-05-04 12:15:35 +08007187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007188 pthread_mutex_lock(&adev->lock);
7189 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007190 ALOGD("%s: mode %d\n", __func__, mode);
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05307191 if (amplifier_set_mode(mode) != 0)
7192 ALOGE("Failed setting amplifier mode");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007193 adev->mode = mode;
Kunlei Zhang0eab0432019-05-21 14:25:57 +08007194 if (voice_is_in_call(adev) &&
7195 (mode == AUDIO_MODE_NORMAL ||
7196 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07007197 list_for_each(node, &adev->usecase_list) {
7198 usecase = node_to_item(node, struct audio_usecase, list);
7199 if (usecase->type == VOICE_CALL)
7200 break;
7201 }
7202 if (usecase &&
7203 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
7204 ret = audio_extn_usb_check_and_set_svc_int(usecase,
7205 true);
7206 if (ret != 0) {
7207 /* default service interval was successfully updated,
7208 reopen USB backend with new service interval */
7209 check_usecases_codec_backend(adev,
7210 usecase,
7211 usecase->out_snd_device);
7212 }
7213 }
7214
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007215 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07007216 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007217 adev->current_call_output = NULL;
kunleiz60c17e72017-05-04 12:15:35 +08007218 // restore device for other active usecases after stop call
7219 list_for_each(node, &adev->usecase_list) {
7220 usecase = node_to_item(node, struct audio_usecase, list);
7221 select_devices(adev, usecase->id);
7222 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007223 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007224 }
7225 pthread_mutex_unlock(&adev->lock);
7226 return 0;
7227}
7228
7229static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
7230{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007231 int ret;
7232
7233 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08007234 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007235 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Derek Chencdd17c72014-11-24 12:39:14 -08007236 if (adev->ext_hw_plugin)
7237 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007238 pthread_mutex_unlock(&adev->lock);
7239
7240 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007241}
7242
7243static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
7244{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007245 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007246 return 0;
7247}
7248
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007249static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007250 const struct audio_config *config)
7251{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007252 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007253
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007254 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
7255 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007256}
7257
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007258static bool adev_input_allow_hifi_record(struct audio_device *adev,
7259 audio_devices_t devices,
7260 audio_input_flags_t flags,
7261 audio_source_t source) {
7262 const bool allowed = true;
7263
7264 if (!audio_is_usb_in_device(devices))
7265 return !allowed;
7266
7267 switch (flags) {
7268 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007269 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07007270 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7271 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007272 default:
7273 return !allowed;
7274 }
7275
7276 switch (source) {
7277 case AUDIO_SOURCE_DEFAULT:
7278 case AUDIO_SOURCE_MIC:
7279 case AUDIO_SOURCE_UNPROCESSED:
7280 break;
7281 default:
7282 return !allowed;
7283 }
7284
7285 switch (adev->mode) {
7286 case 0:
7287 break;
7288 default:
7289 return !allowed;
7290 }
7291
7292 return allowed;
7293}
7294
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007295static int adev_update_voice_comm_input_stream(struct stream_in *in,
7296 struct audio_config *config)
7297{
7298 bool valid_rate = (config->sample_rate == 8000 ||
7299 config->sample_rate == 16000 ||
7300 config->sample_rate == 32000 ||
7301 config->sample_rate == 48000);
7302 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
7303
7304#ifndef COMPRESS_VOIP_ENABLED
kunleizd96526c2018-04-09 11:12:32 +08007305 if (valid_rate && valid_ch &&
Shalini Manjunathad9860422019-08-23 16:38:03 +05307306 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7307 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007308 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7309 in->config = default_pcm_config_voip_copp;
7310 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
7311 DEFAULT_VOIP_BUF_DURATION_MS,
7312 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
7313 } else {
kunleizbdd9ad02018-04-24 10:53:17 +08007314 ALOGW("%s No valid input in voip, use defaults"
7315 "sample rate %u, channel mask 0x%X",
7316 __func__, config->sample_rate, in->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007317 }
7318 in->config.rate = config->sample_rate;
7319 in->sample_rate = config->sample_rate;
7320#else
7321 //XXX needed for voice_extn_compress_voip_open_input_stream
7322 in->config.rate = config->sample_rate;
Shalini Manjunathad9860422019-08-23 16:38:03 +05307323 if((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7324 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7325 voice_extn_compress_voip_is_active(in->dev)) &&
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007326 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7327 valid_rate && valid_ch) {
7328 voice_extn_compress_voip_open_input_stream(in);
7329 // update rate entries to match config from AF
7330 in->config.rate = config->sample_rate;
7331 in->sample_rate = config->sample_rate;
7332 } else {
7333 ALOGW("%s compress voip not active, use defaults", __func__);
7334 }
7335#endif
7336 return 0;
7337}
7338
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007339static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007340 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007341 audio_devices_t devices,
7342 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007343 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307344 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007345 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007346 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007347{
7348 struct audio_device *adev = (struct audio_device *)dev;
7349 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007350 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007351 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007352 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05307353 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007354 bool is_usb_dev = audio_is_usb_in_device(devices);
7355 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
7356 devices,
7357 flags,
7358 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307359
kunleizdff872d2018-08-20 14:40:33 +08007360 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007361 is_usb_dev = false;
7362 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
7363 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
7364 __func__, devices);
7365 }
7366
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007367 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007368
7369 if (!(is_usb_dev && may_use_hifi_record)) {
7370 if (config->sample_rate == 0)
7371 config->sample_rate = 48000;
7372 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7373 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7374 if (config->format == AUDIO_FORMAT_DEFAULT)
7375 config->format = AUDIO_FORMAT_PCM_16_BIT;
7376
7377 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
7378
7379 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
7380 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05307381 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007382
7383 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007384
7385 if (!in) {
7386 ALOGE("failed to allocate input stream");
7387 return -ENOMEM;
7388 }
7389
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307390 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307391 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7392 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007393 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007394 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007395
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007396 in->stream.common.get_sample_rate = in_get_sample_rate;
7397 in->stream.common.set_sample_rate = in_set_sample_rate;
7398 in->stream.common.get_buffer_size = in_get_buffer_size;
7399 in->stream.common.get_channels = in_get_channels;
7400 in->stream.common.get_format = in_get_format;
7401 in->stream.common.set_format = in_set_format;
7402 in->stream.common.standby = in_standby;
7403 in->stream.common.dump = in_dump;
7404 in->stream.common.set_parameters = in_set_parameters;
7405 in->stream.common.get_parameters = in_get_parameters;
7406 in->stream.common.add_audio_effect = in_add_audio_effect;
7407 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7408 in->stream.set_gain = in_set_gain;
7409 in->stream.read = in_read;
7410 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307411 in->stream.get_active_microphones = in_get_active_microphones;
Ramjee Singhacef98f2019-06-28 11:01:25 +05307412#if ANDROID_PLATFORM_SDK_VERSION >= 29
7413 in->stream.set_microphone_direction = in_set_microphone_direction;
7414 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
7415#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007416
7417 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007418 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007419 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007420 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007421 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007422 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007423 in->bit_width = 16;
7424 in->af_period_multiplier = 1;
7425
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007426 if (is_usb_dev && may_use_hifi_record) {
7427 /* HiFi record selects an appropriate format, channel, rate combo
7428 depending on sink capabilities*/
7429 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7430 &config->format,
7431 &in->supported_formats[0],
7432 MAX_SUPPORTED_FORMATS,
7433 &config->channel_mask,
7434 &in->supported_channel_masks[0],
7435 MAX_SUPPORTED_CHANNEL_MASKS,
7436 &config->sample_rate,
7437 &in->supported_sample_rates[0],
7438 MAX_SUPPORTED_SAMPLE_RATES);
7439 if (ret != 0) {
7440 ret = -EINVAL;
7441 goto err_open;
7442 }
7443 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007444 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307445 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05307446 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
7447 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
7448 in->config.format = PCM_FORMAT_S32_LE;
7449 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307450 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
7451 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
7452 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
7453 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7454 bool ret_error = false;
7455 in->bit_width = 24;
7456 /* 24 bit is restricted to UNPROCESSED source only,also format supported
7457 from HAL is 24_packed and 8_24
7458 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
7459 24_packed return error indicating supported format is 24_packed
7460 *> In case of any other source requesting 24 bit or float return error
7461 indicating format supported is 16 bit only.
7462
7463 on error flinger will retry with supported format passed
7464 */
7465 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
7466 (source != AUDIO_SOURCE_CAMCORDER)) {
7467 config->format = AUDIO_FORMAT_PCM_16_BIT;
7468 if (config->sample_rate > 48000)
7469 config->sample_rate = 48000;
7470 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07007471 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
7472 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307473 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
7474 ret_error = true;
7475 }
7476
7477 if (ret_error) {
7478 ret = -EINVAL;
7479 goto err_open;
7480 }
7481 }
7482
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007483 in->channel_mask = config->channel_mask;
7484 in->format = config->format;
7485
7486 in->usecase = USECASE_AUDIO_RECORD;
7487 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
7488 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
7489 is_low_latency = true;
7490#if LOW_LATENCY_CAPTURE_USE_CASE
7491 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
7492#endif
7493 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
7494 }
7495
7496 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
7497 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
7498 in->realtime = 0;
7499 in->usecase = USECASE_AUDIO_RECORD_MMAP;
7500 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07007501 in->config.format = pcm_format_from_audio_format(config->format);
Weiyin Jiangde7925e2018-11-27 18:45:53 +08007502 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007503 in->stream.start = in_start;
7504 in->stream.stop = in_stop;
7505 in->stream.create_mmap_buffer = in_create_mmap_buffer;
7506 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007507 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007508 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
7509 } else if (in->realtime) {
7510 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07007511 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007512 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007513 in->sample_rate = in->config.rate;
7514 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07007515 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007516 in->usecase = USECASE_AUDIO_RECORD_HIFI;
7517 in->config = pcm_config_audio_capture;
7518 frame_size = audio_stream_in_frame_size(&in->stream);
7519 buffer_size = get_input_buffer_size(config->sample_rate,
7520 config->format,
7521 channel_count,
7522 false /*is_low_latency*/);
7523 in->config.period_size = buffer_size / frame_size;
7524 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007525 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07007526 switch (config->format) {
7527 case AUDIO_FORMAT_PCM_32_BIT:
7528 in->bit_width = 32;
7529 break;
7530 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
7531 case AUDIO_FORMAT_PCM_8_24_BIT:
7532 in->bit_width = 24;
7533 break;
7534 default:
7535 in->bit_width = 16;
7536 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007537 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007538 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007539 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05307540 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007541 if (config->sample_rate == 0)
7542 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7543 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
7544 config->sample_rate != 8000) {
7545 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7546 ret = -EINVAL;
7547 goto err_open;
7548 }
7549 if (config->format == AUDIO_FORMAT_DEFAULT)
7550 config->format = AUDIO_FORMAT_PCM_16_BIT;
7551 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
7552 config->format = AUDIO_FORMAT_PCM_16_BIT;
7553 ret = -EINVAL;
7554 goto err_open;
7555 }
7556
7557 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
7558 in->config = pcm_config_afe_proxy_record;
7559 in->config.channels = channel_count;
7560 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307561 in->sample_rate = config->sample_rate;
Haynes Mathew George46740472017-10-27 18:40:12 -07007562 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05307563 int ret_val;
7564 pthread_mutex_lock(&adev->lock);
7565 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
7566 in, config, &channel_mask_updated);
7567 pthread_mutex_unlock(&adev->lock);
7568
7569 if (!ret_val) {
7570 if (channel_mask_updated == true) {
7571 ALOGD("%s: return error to retry with updated channel mask (%#x)",
7572 __func__, config->channel_mask);
7573 ret = -EINVAL;
7574 goto err_open;
7575 }
7576 ALOGD("%s: created multi-channel session succesfully",__func__);
7577 } else if (audio_extn_compr_cap_enabled() &&
7578 audio_extn_compr_cap_format_supported(config->format) &&
7579 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
7580 audio_extn_compr_cap_init(in);
7581 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05307582 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05307583 ret = audio_extn_cin_configure_input_stream(in);
7584 if (ret)
7585 goto err_open;
7586 } else {
7587 in->config = pcm_config_audio_capture;
7588 in->config.rate = config->sample_rate;
7589 in->config.format = pcm_format_from_audio_format(config->format);
7590 in->config.channels = channel_count;
7591 in->sample_rate = config->sample_rate;
7592 in->format = config->format;
7593 frame_size = audio_stream_in_frame_size(&in->stream);
7594 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07007595 config->format,
7596 channel_count,
7597 is_low_latency);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307598 in->config.period_size = buffer_size / frame_size;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007599
Revathi Uddarajud2634032017-12-07 14:42:34 +05307600 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
7601 /* optionally use VOIP usecase depending on config(s) */
7602 ret = adev_update_voice_comm_input_stream(in, config);
7603 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007604
Revathi Uddarajud2634032017-12-07 14:42:34 +05307605 if (ret) {
7606 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
7607 goto err_open;
7608 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007609 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007610 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307611 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7612 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007613 devices, flags, in->format,
7614 in->sample_rate, in->bit_width,
7615 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307616 register_format(in->format, in->supported_formats);
7617 register_channel_mask(in->channel_mask, in->supported_channel_masks);
7618 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307619
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007620 /* This stream could be for sound trigger lab,
7621 get sound trigger pcm if present */
7622 audio_extn_sound_trigger_check_and_get_session(in);
7623
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307624 lock_input_stream(in);
7625 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
7626 pthread_mutex_lock(&adev->lock);
7627 in->card_status = adev->card_status;
7628 pthread_mutex_unlock(&adev->lock);
7629 pthread_mutex_unlock(&in->lock);
7630
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007631 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07007632 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007633 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007634
7635err_open:
7636 free(in);
7637 *stream_in = NULL;
7638 return ret;
7639}
7640
7641static void adev_close_input_stream(struct audio_hw_device *dev,
7642 struct audio_stream_in *stream)
7643{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007644 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007645 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007646 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307647
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307648 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007649
kunleizef40adb2018-12-28 17:50:23 +08007650 /* must deregister from sndmonitor first to prevent races
7651 * between the callback and close_stream
7652 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307653 audio_extn_snd_mon_unregister_listener(stream);
7654
kunleizef40adb2018-12-28 17:50:23 +08007655 /* Disable echo reference if there are no active input, hfp call
7656 * and sound trigger while closing input stream
7657 */
7658 if (!adev->active_input &&
7659 !audio_extn_hfp_is_active(adev) &&
7660 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8405edd2018-11-29 15:04:56 +08007661 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleizef40adb2018-12-28 17:50:23 +08007662 else
7663 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307664
Pallavid7c7a272018-01-16 11:22:55 +05307665 if (in == NULL) {
7666 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
7667 return;
7668 }
7669
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007670 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307671 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007672 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307673 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007674 if (ret != 0)
7675 ALOGE("%s: Compress voip input cannot be closed, error:%d",
7676 __func__, ret);
7677 } else
7678 in_standby(&stream->common);
7679
Revathi Uddarajud2634032017-12-07 14:42:34 +05307680 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07007681 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007682 audio_extn_ssr_deinit();
7683 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007684
Garmond Leunge2433c32017-09-28 21:51:22 -07007685 if (audio_extn_ffv_get_stream() == in) {
7686 audio_extn_ffv_stream_deinit();
7687 }
7688
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307689 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07007690 audio_extn_compr_cap_format_supported(in->config.format))
7691 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05307692
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307693 if (audio_extn_cin_attached_usecase(in->usecase))
7694 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007695
Mingming Yinfd7607b2016-01-22 12:48:44 -08007696 if (in->is_st_session) {
7697 ALOGV("%s: sound trigger pcm stop lab", __func__);
7698 audio_extn_sound_trigger_stop_lab(in);
7699 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007700 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307701 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007702 return;
7703}
7704
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307705int adev_create_audio_patch(struct audio_hw_device *dev,
7706 unsigned int num_sources,
7707 const struct audio_port_config *sources,
7708 unsigned int num_sinks,
7709 const struct audio_port_config *sinks,
7710 audio_patch_handle_t *handle)
7711{
7712
7713
7714 return audio_extn_hw_loopback_create_audio_patch(dev,
7715 num_sources,
7716 sources,
7717 num_sinks,
7718 sinks,
7719 handle);
7720
7721}
7722
7723int adev_release_audio_patch(struct audio_hw_device *dev,
7724 audio_patch_handle_t handle)
7725{
7726 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
7727}
7728
7729int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
7730{
7731 return audio_extn_hw_loopback_get_audio_port(dev, config);
7732}
7733
7734int adev_set_audio_port_config(struct audio_hw_device *dev,
7735 const struct audio_port_config *config)
7736{
7737 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
7738}
7739
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007740static int adev_dump(const audio_hw_device_t *device __unused,
7741 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007742{
7743 return 0;
7744}
7745
7746static int adev_close(hw_device_t *device)
7747{
Preetam Singh Ranawat624cc802019-06-24 15:11:28 +05307748 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07007749
Preetam Singh Ranawat624cc802019-06-24 15:11:28 +05307750 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07007751 return 0;
7752
7753 pthread_mutex_lock(&adev_init_lock);
7754
7755 if ((--audio_device_ref_count) == 0) {
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05307756 if (amplifier_close() != 0)
7757 ALOGE("Amplifier close failed");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307758 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007759 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08007760 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307761 audio_extn_utils_release_streams_cfg_lists(
7762 &adev->streams_output_cfg_list,
7763 &adev->streams_input_cfg_list);
Sidipotu Ashokafffd202019-05-06 15:41:56 +05307764 if (audio_extn_qap_is_enabled())
7765 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307766 if (audio_extn_qaf_is_enabled())
7767 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007768 audio_route_free(adev->audio_route);
Weiyin Jiang902f7d12019-03-05 23:39:45 +08007769 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07007770 free(adev->snd_dev_ref_cnt);
7771 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007772 if (adev->adm_deinit)
7773 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307774 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007775 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307776 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307777 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007778 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307779 if (adev->device_cfg_params) {
7780 free(adev->device_cfg_params);
7781 adev->device_cfg_params = NULL;
7782 }
Derek Chencdd17c72014-11-24 12:39:14 -08007783 if(adev->ext_hw_plugin)
7784 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Kiran Kandi910e1862013-10-29 13:29:42 -07007785 free(device);
7786 adev = NULL;
7787 }
Balázs Triszka6e101332018-02-26 22:11:10 +01007788
7789 us_deinit();
7790
Kiran Kandi910e1862013-10-29 13:29:42 -07007791 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchaa1358992018-11-14 13:25:08 +05307792 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007793 return 0;
7794}
7795
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007796/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
7797 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
7798 * just that it _might_ work.
7799 */
7800static int period_size_is_plausible_for_low_latency(int period_size)
7801{
7802 switch (period_size) {
7803 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07007804 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007805 case 240:
7806 case 320:
7807 case 480:
7808 return 1;
7809 default:
7810 return 0;
7811 }
7812}
7813
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307814static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
7815{
7816 bool is_snd_card_status = false;
7817 bool is_ext_device_status = false;
7818 char value[32];
7819 int card = -1;
7820 card_status_t status;
7821
7822 if (cookie != adev || !parms)
7823 return;
7824
7825 if (!parse_snd_card_status(parms, &card, &status)) {
7826 is_snd_card_status = true;
7827 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
7828 is_ext_device_status = true;
7829 } else {
7830 // not a valid event
7831 return;
7832 }
7833
7834 pthread_mutex_lock(&adev->lock);
7835 if (card == adev->snd_card || is_ext_device_status) {
7836 if (is_snd_card_status && adev->card_status != status) {
7837 adev->card_status = status;
7838 platform_snd_card_update(adev->platform, status);
7839 audio_extn_fm_set_parameters(adev, parms);
7840 } else if (is_ext_device_status) {
7841 platform_set_parameters(adev->platform, parms);
7842 }
7843 }
7844 pthread_mutex_unlock(&adev->lock);
7845 return;
7846}
7847
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307848/* out and adev lock held */
7849static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
7850{
7851 struct audio_usecase *uc_info;
7852 float left_p;
7853 float right_p;
7854 audio_devices_t devices;
7855
7856 uc_info = get_usecase_from_list(adev, out->usecase);
7857 if (uc_info == NULL) {
7858 ALOGE("%s: Could not find the usecase (%d) in the list",
7859 __func__, out->usecase);
7860 return -EINVAL;
7861 }
7862
7863 ALOGD("%s: enter: usecase(%d: %s)", __func__,
7864 out->usecase, use_case_table[out->usecase]);
7865
7866 if (restore) {
7867 // restore A2DP device for active usecases and unmute if required
7868 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
7869 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
7870 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
7871 select_devices(adev, uc_info->id);
7872 pthread_mutex_lock(&out->compr_mute_lock);
7873 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7874 (out->a2dp_compress_mute)) {
7875 out->a2dp_compress_mute = false;
7876 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
7877 }
7878 pthread_mutex_unlock(&out->compr_mute_lock);
7879 }
7880 } else {
7881 // mute compress stream if suspended
7882 pthread_mutex_lock(&out->compr_mute_lock);
7883 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7884 (!out->a2dp_compress_mute)) {
7885 if (!out->standby) {
7886 ALOGD("%s: selecting speaker and muting stream", __func__);
7887 devices = out->devices;
7888 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
7889 left_p = out->volume_l;
7890 right_p = out->volume_r;
7891 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7892 compress_pause(out->compr);
7893 out_set_compr_volume(&out->stream, (float)0, (float)0);
7894 out->a2dp_compress_mute = true;
7895 select_devices(adev, out->usecase);
7896 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7897 compress_resume(out->compr);
7898 out->devices = devices;
7899 out->volume_l = left_p;
7900 out->volume_r = right_p;
7901 }
7902 }
7903 pthread_mutex_unlock(&out->compr_mute_lock);
7904 }
7905 ALOGV("%s: exit", __func__);
7906 return 0;
7907}
7908
7909int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
7910{
7911 int ret = 0;
7912
7913 lock_output_stream(out);
7914 pthread_mutex_lock(&adev->lock);
7915
7916 ret = check_a2dp_restore_l(adev, out, restore);
7917
7918 pthread_mutex_unlock(&adev->lock);
7919 pthread_mutex_unlock(&out->lock);
7920 return ret;
7921}
7922
Haynes Mathew George01156f92018-04-13 15:29:54 -07007923void adev_on_battery_status_changed(bool charging)
7924{
7925 pthread_mutex_lock(&adev->lock);
7926 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
7927 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08007928 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07007929 pthread_mutex_unlock(&adev->lock);
7930}
7931
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007932static int adev_open(const hw_module_t *module, const char *name,
7933 hw_device_t **device)
7934{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307935 int ret;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05307936 char mixer_ctl_name[128] = {0};
7937 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307938
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007939 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007940 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
7941
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007942 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07007943 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007944 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07007945 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007946 ALOGD("%s: returning existing instance of adev", __func__);
7947 ALOGD("%s: exit", __func__);
7948 pthread_mutex_unlock(&adev_init_lock);
7949 return 0;
7950 }
7951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007952 adev = calloc(1, sizeof(struct audio_device));
7953
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007954 if (!adev) {
7955 pthread_mutex_unlock(&adev_init_lock);
7956 return -ENOMEM;
7957 }
7958
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007959 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
7960
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05307961#ifdef DYNAMIC_LOG_ENABLED
7962 register_for_dynamic_logging("hal");
7963#endif
7964
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007965 adev->device.common.tag = HARDWARE_DEVICE_TAG;
7966 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7967 adev->device.common.module = (struct hw_module_t *)module;
7968 adev->device.common.close = adev_close;
7969
7970 adev->device.init_check = adev_init_check;
7971 adev->device.set_voice_volume = adev_set_voice_volume;
7972 adev->device.set_master_volume = adev_set_master_volume;
7973 adev->device.get_master_volume = adev_get_master_volume;
7974 adev->device.set_master_mute = adev_set_master_mute;
7975 adev->device.get_master_mute = adev_get_master_mute;
7976 adev->device.set_mode = adev_set_mode;
7977 adev->device.set_mic_mute = adev_set_mic_mute;
7978 adev->device.get_mic_mute = adev_get_mic_mute;
7979 adev->device.set_parameters = adev_set_parameters;
7980 adev->device.get_parameters = adev_get_parameters;
7981 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
7982 adev->device.open_output_stream = adev_open_output_stream;
7983 adev->device.close_output_stream = adev_close_output_stream;
7984 adev->device.open_input_stream = adev_open_input_stream;
7985 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307986 adev->device.create_audio_patch = adev_create_audio_patch;
7987 adev->device.release_audio_patch = adev_release_audio_patch;
7988 adev->device.get_audio_port = adev_get_audio_port;
7989 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007990 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307991 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007992
7993 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007994 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08007995 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007996 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007997 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007998 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08007999 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07008000 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308001 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07008002 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07008003 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008004 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08008005 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08008006 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008007 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05308008 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308009 adev->perf_lock_opts[0] = 0x101;
8010 adev->perf_lock_opts[1] = 0x20E;
8011 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008012 adev->dsp_bit_width_enforce_mode = 0;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05308013 adev->use_old_pspd_mix_ctrl = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308014
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008015 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07008016 adev->platform = platform_init(adev);
8017 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008018 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008019 free(adev->snd_dev_ref_cnt);
8020 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008021 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07008022 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8023 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08008024 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008025 return -EINVAL;
8026 }
Eric Laurentc4aef752013-09-12 17:45:53 -07008027
Sidipotu Ashokafffd202019-05-06 15:41:56 +05308028 if (audio_extn_qap_is_enabled()) {
8029 ret = audio_extn_qap_init(adev);
8030 if (ret < 0) {
8031 pthread_mutex_destroy(&adev->lock);
8032 free(adev);
8033 adev = NULL;
8034 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8035 *device = NULL;
8036 pthread_mutex_unlock(&adev_init_lock);
8037 return ret;
8038 }
8039 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
8040 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
8041 }
8042
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308043 if (audio_extn_qaf_is_enabled()) {
8044 ret = audio_extn_qaf_init(adev);
8045 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008046 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308047 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008048 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308049 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8050 *device = NULL;
8051 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308052 return ret;
8053 }
8054
8055 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
8056 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
8057 }
8058
Derek Chencdd17c72014-11-24 12:39:14 -08008059 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
8060
Eric Laurentc4aef752013-09-12 17:45:53 -07008061 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
8062 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
8063 if (adev->visualizer_lib == NULL) {
8064 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
8065 } else {
8066 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
8067 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008068 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008069 "visualizer_hal_start_output");
8070 adev->visualizer_stop_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_stop_output");
8073 }
8074 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05308075 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08008076 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08008077 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308078 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008079 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07008080
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008081 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
8082 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
8083 if (adev->offload_effects_lib == NULL) {
8084 ALOGE("%s: DLOPEN failed for %s", __func__,
8085 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8086 } else {
8087 ALOGV("%s: DLOPEN successful for %s", __func__,
8088 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8089 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05308090 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008091 "offload_effects_bundle_hal_start_output");
8092 adev->offload_effects_stop_output =
8093 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
8094 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008095 adev->offload_effects_set_hpx_state =
8096 (int (*)(bool))dlsym(adev->offload_effects_lib,
8097 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05308098 adev->offload_effects_get_parameters =
8099 (void (*)(struct str_parms *, struct str_parms *))
8100 dlsym(adev->offload_effects_lib,
8101 "offload_effects_bundle_get_parameters");
8102 adev->offload_effects_set_parameters =
8103 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
8104 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008105 }
8106 }
8107
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008108 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
8109 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
8110 if (adev->adm_lib == NULL) {
8111 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
8112 } else {
8113 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
8114 adev->adm_init = (adm_init_t)
8115 dlsym(adev->adm_lib, "adm_init");
8116 adev->adm_deinit = (adm_deinit_t)
8117 dlsym(adev->adm_lib, "adm_deinit");
8118 adev->adm_register_input_stream = (adm_register_input_stream_t)
8119 dlsym(adev->adm_lib, "adm_register_input_stream");
8120 adev->adm_register_output_stream = (adm_register_output_stream_t)
8121 dlsym(adev->adm_lib, "adm_register_output_stream");
8122 adev->adm_deregister_stream = (adm_deregister_stream_t)
8123 dlsym(adev->adm_lib, "adm_deregister_stream");
8124 adev->adm_request_focus = (adm_request_focus_t)
8125 dlsym(adev->adm_lib, "adm_request_focus");
8126 adev->adm_abandon_focus = (adm_abandon_focus_t)
8127 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008128 adev->adm_set_config = (adm_set_config_t)
8129 dlsym(adev->adm_lib, "adm_set_config");
8130 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
8131 dlsym(adev->adm_lib, "adm_request_focus_v2");
8132 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
8133 dlsym(adev->adm_lib, "adm_is_noirq_avail");
8134 adev->adm_on_routing_change = (adm_on_routing_change_t)
8135 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008136 }
8137 }
8138
Mingming Yin514a8bc2014-07-29 15:22:21 -07008139 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008140 //initialize this to false for now,
8141 //this will be set to true through set param
8142 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07008143
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07008144 audio_extn_ds2_enable(adev);
Balázs Triszka6e101332018-02-26 22:11:10 +01008145
8146 us_init(adev);
8147
Daniel Hillenbrand53932c92013-05-23 10:10:00 +05308148 if (amplifier_open(adev) != 0)
8149 ALOGE("Amplifier initialization failed");
8150
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008151 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008152 adev->dsp_bit_width_enforce_mode =
8153 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008154
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308155 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
8156 &adev->streams_output_cfg_list,
8157 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008158
Kiran Kandi910e1862013-10-29 13:29:42 -07008159 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008160
8161 char value[PROPERTY_VALUE_MAX];
8162 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008163 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008164 trial = atoi(value);
8165 if (period_size_is_plausible_for_low_latency(trial)) {
8166 pcm_config_low_latency.period_size = trial;
8167 pcm_config_low_latency.start_threshold = trial / 4;
8168 pcm_config_low_latency.avail_min = trial / 4;
8169 configured_low_latency_capture_period_size = trial;
8170 }
8171 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008172 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008173 trial = atoi(value);
8174 if (period_size_is_plausible_for_low_latency(trial)) {
8175 configured_low_latency_capture_period_size = trial;
8176 }
8177 }
8178
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08008179 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
8180
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008181 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008182 af_period_multiplier = atoi(value);
8183 if (af_period_multiplier < 0)
8184 af_period_multiplier = 2;
8185 else if (af_period_multiplier > 4)
8186 af_period_multiplier = 4;
8187
8188 ALOGV("new period_multiplier = %d", af_period_multiplier);
8189 }
8190
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008191 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008192 pthread_mutex_unlock(&adev_init_lock);
8193
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008194 if (adev->adm_init)
8195 adev->adm_data = adev->adm_init();
8196
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308197 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308198 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008199 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308200
8201 audio_extn_snd_mon_init();
8202 pthread_mutex_lock(&adev->lock);
8203 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
8204 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07008205 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
8206 /*
8207 * if the battery state callback happens before charging can be queried,
8208 * it will be guarded with the adev->lock held in the cb function and so
8209 * the callback value will reflect the latest state
8210 */
8211 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308212 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08008213 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
8214 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308215 /* Allocate memory for Device config params */
8216 adev->device_cfg_params = (struct audio_device_config_param*)
8217 calloc(platform_get_max_codec_backend(),
8218 sizeof(struct audio_device_config_param));
8219 if (adev->device_cfg_params == NULL)
8220 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308221
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05308222 /*
8223 * Check if new PSPD matrix mixer control is supported. If not
8224 * supported, then set flag so that old mixer ctrl is sent while
8225 * sending pspd coefficients on older kernel version. Query mixer
8226 * control for default pcm id and channel value one.
8227 */
8228 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
8229 "AudStr %d ChMixer Weight Ch %d", 0, 1);
8230
8231 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
8232 if (!ctl) {
8233 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
8234 __func__, mixer_ctl_name);
8235 adev->use_old_pspd_mix_ctrl = true;
8236 }
8237
Eric Laurent994a6932013-07-17 11:51:42 -07008238 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008239 return 0;
8240}
8241
8242static struct hw_module_methods_t hal_module_methods = {
8243 .open = adev_open,
8244};
8245
8246struct audio_module HAL_MODULE_INFO_SYM = {
8247 .common = {
8248 .tag = HARDWARE_MODULE_TAG,
8249 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
8250 .hal_api_version = HARDWARE_HAL_API_VERSION,
8251 .id = AUDIO_HARDWARE_MODULE_ID,
8252 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08008253 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008254 .methods = &hal_module_methods,
8255 },
8256};