blob: f31991a7442b8f77a50b8a2d62d73903e8c798ca [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05302 * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070066#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070068#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053077#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080080#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080081
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053082#ifdef DYNAMIC_LOG_ENABLED
83#include <log_xml_parser.h>
84#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
85#include <log_utils.h>
86#endif
87
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053089/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
90#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070092#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053093#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070095#define PROXY_OPEN_RETRY_COUNT 100
96#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080097
Mingming Yin08c7e312015-03-16 18:10:58 -070098#ifdef USE_LL_AS_PRIMARY_OUTPUT
99#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
100#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
101#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800102#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700103#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
104#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800105
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700106#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700107#define DEFAULT_VOIP_BUF_DURATION_MS 20
108#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
109#define DEFAULT_VOIP_SAMP_RATE 48000
110
111#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
112
113struct pcm_config default_pcm_config_voip_copp = {
114 .channels = 1,
115 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
116 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
117 .period_count = 2,
118 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800119 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
120 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700121};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700122
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700123#define MIN_CHANNEL_COUNT 1
124#define DEFAULT_CHANNEL_COUNT 2
125#define MAX_HIFI_CHANNEL_COUNT 8
126
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700127static unsigned int configured_low_latency_capture_period_size =
128 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
129
Haynes Mathew George16081042017-05-31 17:16:49 -0700130#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
131#define MMAP_PERIOD_COUNT_MIN 32
132#define MMAP_PERIOD_COUNT_MAX 512
133#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
134
Eric Laurentb23d5282013-05-14 15:27:20 -0700135struct pcm_config pcm_config_deep_buffer = {
136 .channels = 2,
137 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
138 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
139 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
140 .format = PCM_FORMAT_S16_LE,
141 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
142 .stop_threshold = INT_MAX,
143 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
144};
145
146struct pcm_config pcm_config_low_latency = {
147 .channels = 2,
148 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
149 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
150 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
151 .format = PCM_FORMAT_S16_LE,
152 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
153 .stop_threshold = INT_MAX,
154 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
155};
156
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700157static int af_period_multiplier = 4;
158struct pcm_config pcm_config_rt = {
159 .channels = 2,
160 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
161 .period_size = ULL_PERIOD_SIZE, //1 ms
162 .period_count = 512, //=> buffer size is 512ms
163 .format = PCM_FORMAT_S16_LE,
164 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
165 .stop_threshold = INT_MAX,
166 .silence_threshold = 0,
167 .silence_size = 0,
168 .avail_min = ULL_PERIOD_SIZE, //1 ms
169};
170
Eric Laurentb23d5282013-05-14 15:27:20 -0700171struct pcm_config pcm_config_hdmi_multi = {
172 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
173 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
174 .period_size = HDMI_MULTI_PERIOD_SIZE,
175 .period_count = HDMI_MULTI_PERIOD_COUNT,
176 .format = PCM_FORMAT_S16_LE,
177 .start_threshold = 0,
178 .stop_threshold = INT_MAX,
179 .avail_min = 0,
180};
181
Haynes Mathew George16081042017-05-31 17:16:49 -0700182struct pcm_config pcm_config_mmap_playback = {
183 .channels = 2,
184 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
185 .period_size = MMAP_PERIOD_SIZE,
186 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
187 .format = PCM_FORMAT_S16_LE,
188 .start_threshold = MMAP_PERIOD_SIZE*8,
189 .stop_threshold = INT32_MAX,
190 .silence_threshold = 0,
191 .silence_size = 0,
192 .avail_min = MMAP_PERIOD_SIZE, //1 ms
193};
194
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700195struct pcm_config pcm_config_hifi = {
196 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
197 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
198 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
199 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
200 .format = PCM_FORMAT_S24_3LE,
201 .start_threshold = 0,
202 .stop_threshold = INT_MAX,
203 .avail_min = 0,
204};
205
Eric Laurentb23d5282013-05-14 15:27:20 -0700206struct pcm_config pcm_config_audio_capture = {
207 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700208 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
209 .format = PCM_FORMAT_S16_LE,
210};
211
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700212struct pcm_config pcm_config_audio_capture_rt = {
213 .channels = 2,
214 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
215 .period_size = ULL_PERIOD_SIZE,
216 .period_count = 512,
217 .format = PCM_FORMAT_S16_LE,
218 .start_threshold = 0,
219 .stop_threshold = INT_MAX,
220 .silence_threshold = 0,
221 .silence_size = 0,
222 .avail_min = ULL_PERIOD_SIZE, //1 ms
223};
224
Haynes Mathew George16081042017-05-31 17:16:49 -0700225struct pcm_config pcm_config_mmap_capture = {
226 .channels = 2,
227 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
228 .period_size = MMAP_PERIOD_SIZE,
229 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
230 .format = PCM_FORMAT_S16_LE,
231 .start_threshold = 0,
232 .stop_threshold = INT_MAX,
233 .silence_threshold = 0,
234 .silence_size = 0,
235 .avail_min = MMAP_PERIOD_SIZE, //1 ms
236};
237
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700238#define AFE_PROXY_CHANNEL_COUNT 2
239#define AFE_PROXY_SAMPLING_RATE 48000
240
241#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
242#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
243
244struct pcm_config pcm_config_afe_proxy_playback = {
245 .channels = AFE_PROXY_CHANNEL_COUNT,
246 .rate = AFE_PROXY_SAMPLING_RATE,
247 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
248 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
249 .format = PCM_FORMAT_S16_LE,
250 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
251 .stop_threshold = INT_MAX,
252 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
253};
254
255#define AFE_PROXY_RECORD_PERIOD_SIZE 768
256#define AFE_PROXY_RECORD_PERIOD_COUNT 4
257
258struct pcm_config pcm_config_afe_proxy_record = {
259 .channels = AFE_PROXY_CHANNEL_COUNT,
260 .rate = AFE_PROXY_SAMPLING_RATE,
261 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
262 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
263 .format = PCM_FORMAT_S16_LE,
264 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
265 .stop_threshold = INT_MAX,
266 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
267};
268
Ashish Jainf1eaa582016-05-23 20:54:24 +0530269#define AUDIO_MAX_PCM_FORMATS 7
270
271const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
272 [AUDIO_FORMAT_DEFAULT] = 0,
273 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
274 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
275 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
276 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
277 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
278 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
279};
280
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800281const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700282 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
283 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700284 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
285 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700286 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700287 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700288 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
289 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
290 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
291 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
292 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
293 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
294 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
295 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700296 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
297 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700298 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700299
Eric Laurentb23d5282013-05-14 15:27:20 -0700300 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700301 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530302 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
303 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
304 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530305 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
306 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700307 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700308 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700309 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700310 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700311
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800312 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800313 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700314 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700315
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700316 [USECASE_VOICE2_CALL] = "voice2-call",
317 [USECASE_VOLTE_CALL] = "volte-call",
318 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800319 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800320 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
321 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800322 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700323 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
324 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
325 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800326 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
327 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
328 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
329
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700330 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
331 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700332 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
333 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700334
335 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
336 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530337 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700338
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530339 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530340 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
341 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700342
343 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
344 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530345 /* For Interactive Audio Streams */
346 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
347 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
348 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
349 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
350 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
351 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
352 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
353 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700354
355 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture"
Eric Laurentb23d5282013-05-14 15:27:20 -0700356};
357
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700358static const audio_usecase_t offload_usecases[] = {
359 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700360 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
361 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
362 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
363 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
364 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
365 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
366 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
367 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700368};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800369
Varun Balaraje49253e2017-07-06 19:48:56 +0530370static const audio_usecase_t interactive_usecases[] = {
371 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
372 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
373 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
374 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
375 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
376 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
377 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
378 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
379};
380
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800381#define STRING_TO_ENUM(string) { #string, string }
382
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800383struct string_to_enum {
384 const char *name;
385 uint32_t value;
386};
387
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700388static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800389 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800390 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
391 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
392 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700393 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800394 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
395 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800396 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700397 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
398 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
399 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
400 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
401 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
402 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
403 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
404 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
405 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
406 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
407 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800408};
409
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700410static const struct string_to_enum formats_name_to_enum_table[] = {
411 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
412 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
413 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700414 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
415 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
416 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700417 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800418 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
419 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700420 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800421};
422
423//list of all supported sample rates by HDMI specification.
424static const int out_hdmi_sample_rates[] = {
425 32000, 44100, 48000, 88200, 96000, 176400, 192000,
426};
427
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700428static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800429 STRING_TO_ENUM(32000),
430 STRING_TO_ENUM(44100),
431 STRING_TO_ENUM(48000),
432 STRING_TO_ENUM(88200),
433 STRING_TO_ENUM(96000),
434 STRING_TO_ENUM(176400),
435 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700436};
437
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700438static struct audio_device *adev = NULL;
439static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700440static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700441//cache last MBDRC cal step level
442static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700443
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530444static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
445static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800446static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530447
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700448static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
449 int flags __unused)
450{
451 int dir = 0;
452 switch (uc_id) {
453 case USECASE_AUDIO_RECORD_LOW_LATENCY:
454 dir = 1;
455 case USECASE_AUDIO_PLAYBACK_ULL:
456 break;
457 default:
458 return false;
459 }
460
461 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
462 PCM_PLAYBACK : PCM_CAPTURE);
463 if (adev->adm_is_noirq_avail)
464 return adev->adm_is_noirq_avail(adev->adm_data,
465 adev->snd_card, dev_id, dir);
466 return false;
467}
468
469static void register_out_stream(struct stream_out *out)
470{
471 struct audio_device *adev = out->dev;
472 if (is_offload_usecase(out->usecase) ||
473 !adev->adm_register_output_stream)
474 return;
475
476 // register stream first for backward compatibility
477 adev->adm_register_output_stream(adev->adm_data,
478 out->handle,
479 out->flags);
480
481 if (!adev->adm_set_config)
482 return;
483
484 if (out->realtime)
485 adev->adm_set_config(adev->adm_data,
486 out->handle,
487 out->pcm, &out->config);
488}
489
490static void register_in_stream(struct stream_in *in)
491{
492 struct audio_device *adev = in->dev;
493 if (!adev->adm_register_input_stream)
494 return;
495
496 adev->adm_register_input_stream(adev->adm_data,
497 in->capture_handle,
498 in->flags);
499
500 if (!adev->adm_set_config)
501 return;
502
503 if (in->realtime)
504 adev->adm_set_config(adev->adm_data,
505 in->capture_handle,
506 in->pcm,
507 &in->config);
508}
509
510static void request_out_focus(struct stream_out *out, long ns)
511{
512 struct audio_device *adev = out->dev;
513
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700514 if (adev->adm_request_focus_v2)
515 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
516 else if (adev->adm_request_focus)
517 adev->adm_request_focus(adev->adm_data, out->handle);
518}
519
520static void request_in_focus(struct stream_in *in, long ns)
521{
522 struct audio_device *adev = in->dev;
523
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700524 if (adev->adm_request_focus_v2)
525 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
526 else if (adev->adm_request_focus)
527 adev->adm_request_focus(adev->adm_data, in->capture_handle);
528}
529
530static void release_out_focus(struct stream_out *out)
531{
532 struct audio_device *adev = out->dev;
533
534 if (adev->adm_abandon_focus)
535 adev->adm_abandon_focus(adev->adm_data, out->handle);
536}
537
538static void release_in_focus(struct stream_in *in)
539{
540 struct audio_device *adev = in->dev;
541 if (adev->adm_abandon_focus)
542 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
543}
544
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530545static int parse_snd_card_status(struct str_parms *parms, int *card,
546 card_status_t *status)
547{
548 char value[32]={0};
549 char state[32]={0};
550
551 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
552 if (ret < 0)
553 return -1;
554
555 // sscanf should be okay as value is of max length 32.
556 // same as sizeof state.
557 if (sscanf(value, "%d,%s", card, state) < 2)
558 return -1;
559
560 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
561 CARD_STATUS_OFFLINE;
562 return 0;
563}
564
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700565static inline void adjust_frames_for_device_delay(struct stream_out *out,
566 uint32_t *dsp_frames) {
567 // Adjustment accounts for A2dp encoder latency with offload usecases
568 // Note: Encoder latency is returned in ms.
569 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
570 unsigned long offset =
571 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
572 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
573 }
574}
575
vivek mehtaa76401a2015-04-24 14:12:15 -0700576__attribute__ ((visibility ("default")))
577bool audio_hw_send_gain_dep_calibration(int level) {
578 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700579 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700580
581 pthread_mutex_lock(&adev_init_lock);
582
583 if (adev != NULL && adev->platform != NULL) {
584 pthread_mutex_lock(&adev->lock);
585 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700586
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530587 // cache level info for any of the use case which
588 // was not started.
589 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700590
vivek mehtaa76401a2015-04-24 14:12:15 -0700591 pthread_mutex_unlock(&adev->lock);
592 } else {
593 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
594 }
595
596 pthread_mutex_unlock(&adev_init_lock);
597
598 return ret_val;
599}
600
Ashish Jain5106d362016-05-11 19:23:33 +0530601static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
602{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800603 bool gapless_enabled = false;
604 const char *mixer_ctl_name = "Compress Gapless Playback";
605 struct mixer_ctl *ctl;
606
607 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700608 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530609
610 /*Disable gapless if its AV playback*/
611 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800612
613 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
614 if (!ctl) {
615 ALOGE("%s: Could not get ctl for mixer cmd - %s",
616 __func__, mixer_ctl_name);
617 return -EINVAL;
618 }
619
620 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
621 ALOGE("%s: Could not set gapless mode %d",
622 __func__, gapless_enabled);
623 return -EINVAL;
624 }
625 return 0;
626}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700627
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700628__attribute__ ((visibility ("default")))
629int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
630 int table_size) {
631 int ret_val = 0;
632 ALOGV("%s: enter ... ", __func__);
633
634 pthread_mutex_lock(&adev_init_lock);
635 if (adev == NULL) {
636 ALOGW("%s: adev is NULL .... ", __func__);
637 goto done;
638 }
639
640 pthread_mutex_lock(&adev->lock);
641 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
642 pthread_mutex_unlock(&adev->lock);
643done:
644 pthread_mutex_unlock(&adev_init_lock);
645 ALOGV("%s: exit ... ", __func__);
646 return ret_val;
647}
648
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700649static bool is_supported_format(audio_format_t format)
650{
Eric Laurent86e17132013-09-12 17:49:30 -0700651 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530652 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530653 format == AUDIO_FORMAT_AAC_LC ||
654 format == AUDIO_FORMAT_AAC_HE_V1 ||
655 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530656 format == AUDIO_FORMAT_AAC_ADTS_LC ||
657 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
658 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530659 format == AUDIO_FORMAT_AAC_LATM_LC ||
660 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
661 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530662 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
663 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530664 format == AUDIO_FORMAT_PCM_FLOAT ||
665 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700666 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530667 format == AUDIO_FORMAT_AC3 ||
668 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700669 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530670 format == AUDIO_FORMAT_DTS ||
671 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800672 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530673 format == AUDIO_FORMAT_ALAC ||
674 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530675 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530676 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800677 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530678 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700679 format == AUDIO_FORMAT_APTX ||
680 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800681 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700682
683 return false;
684}
685
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700686static inline bool is_mmap_usecase(audio_usecase_t uc_id)
687{
688 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
689 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
690}
691
Avinash Vaish71a8b972014-07-24 15:36:33 +0530692static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
693 struct audio_usecase *uc_info)
694{
695 struct listnode *node;
696 struct audio_usecase *usecase;
697
698 if (uc_info == NULL)
699 return -EINVAL;
700
701 /* Re-route all voice usecases on the shared backend other than the
702 specified usecase to new snd devices */
703 list_for_each(node, &adev->usecase_list) {
704 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800705 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530706 enable_audio_route(adev, usecase);
707 }
708 return 0;
709}
710
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530711static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530712{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530713 ALOGV("%s", __func__);
714 audio_route_apply_and_update_path(adev->audio_route,
715 "asrc-mode");
716 adev->asrc_mode_enabled = true;
717}
718
719static void disable_asrc_mode(struct audio_device *adev)
720{
721 ALOGV("%s", __func__);
722 audio_route_reset_and_update_path(adev->audio_route,
723 "asrc-mode");
724 adev->asrc_mode_enabled = false;
725}
726
727/*
728 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
729 * 44.1 or Native DSD backends are enabled for any of current use case.
730 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
731 * - Disable current mix path use case(Headphone backend) and re-enable it with
732 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
733 * e.g. Naitve DSD or Headphone 44.1 -> + 48
734 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530735static void check_and_set_asrc_mode(struct audio_device *adev,
736 struct audio_usecase *uc_info,
737 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530738{
739 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530740 int i, num_new_devices = 0;
741 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
742 /*
743 *Split snd device for new combo use case
744 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
745 */
746 if (platform_split_snd_device(adev->platform,
747 snd_device,
748 &num_new_devices,
749 split_new_snd_devices) == 0) {
750 for (i = 0; i < num_new_devices; i++)
751 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
752 } else {
753 int new_backend_idx = platform_get_backend_index(snd_device);
754 if (((new_backend_idx == HEADPHONE_BACKEND) ||
755 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
756 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
757 !adev->asrc_mode_enabled) {
758 struct listnode *node = NULL;
759 struct audio_usecase *uc = NULL;
760 struct stream_out *curr_out = NULL;
761 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
762 int i, num_devices, ret = 0;
763 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530764
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530765 list_for_each(node, &adev->usecase_list) {
766 uc = node_to_item(node, struct audio_usecase, list);
767 curr_out = (struct stream_out*) uc->stream.out;
768 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
769 /*
770 *Split snd device for existing combo use case
771 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
772 */
773 ret = platform_split_snd_device(adev->platform,
774 uc->out_snd_device,
775 &num_devices,
776 split_snd_devices);
777 if (ret < 0 || num_devices == 0) {
778 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
779 split_snd_devices[0] = uc->out_snd_device;
780 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800781 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530782 for (i = 0; i < num_devices; i++) {
783 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
784 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
785 if((new_backend_idx == HEADPHONE_BACKEND) &&
786 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
787 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
788 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
789 __func__);
790 enable_asrc_mode(adev);
791 break;
792 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
793 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
794 (usecase_backend_idx == HEADPHONE_BACKEND)) {
795 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
796 __func__);
797 disable_audio_route(adev, uc);
798 disable_snd_device(adev, uc->out_snd_device);
799 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
800 if (new_backend_idx == DSD_NATIVE_BACKEND)
801 audio_route_apply_and_update_path(adev->audio_route,
802 "hph-true-highquality-mode");
803 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
804 (curr_out->bit_width >= 24))
805 audio_route_apply_and_update_path(adev->audio_route,
806 "hph-highquality-mode");
807 enable_asrc_mode(adev);
808 enable_snd_device(adev, uc->out_snd_device);
809 enable_audio_route(adev, uc);
810 break;
811 }
812 }
813 // reset split devices count
814 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800815 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530816 if (adev->asrc_mode_enabled)
817 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530818 }
819 }
820 }
821}
822
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700823#ifdef DYNAMIC_ECNS_ENABLED
824static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
825 struct audio_effect_config effect_config,
826 unsigned int param_value)
827{
828 char mixer_ctl_name[] = "Audio Effect";
829 struct mixer_ctl *ctl;
830 long set_values[6];
831 struct stream_in *in = adev->active_input;
832
833 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
834 if (!ctl) {
835 ALOGE("%s: Could not get mixer ctl - %s",
836 __func__, mixer_ctl_name);
837 return -EINVAL;
838 }
839
840 set_values[0] = 1; //0:Rx 1:Tx
841 set_values[1] = in->app_type_cfg.app_type;
842 set_values[2] = (long)effect_config.module_id;
843 set_values[3] = (long)effect_config.instance_id;
844 set_values[4] = (long)effect_config.param_id;
845 set_values[5] = param_value;
846
847 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
848
849 return 0;
850
851}
852
853static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
854 int effect_type, unsigned int *param_value)
855{
856 int ret = 0;
857 struct audio_effect_config other_effect_config;
858 struct audio_usecase *usecase = NULL;
859 struct stream_in *in = adev->active_input;
860
861 usecase = get_usecase_from_list(adev, in->usecase);
862 if (!usecase)
863 return -EINVAL;
864
865 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
866 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
867 if (ret < 0) {
868 ALOGE("%s Failed to get effect params %d", __func__, ret);
869 return ret;
870 }
871
872 if (module_id == other_effect_config.module_id) {
873 //Same module id for AEC/NS. Values need to be combined
874 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
875 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
876 *param_value |= other_effect_config.param_value;
877 }
878 }
879
880 return ret;
881}
882
883static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
884{
885 struct audio_effect_config effect_config;
886 struct audio_usecase *usecase = NULL;
887 int ret = 0;
888 unsigned int param_value = 0;
889 struct stream_in *in = adev->active_input;
890
891 if (!in) {
892 ALOGE("%s: Invalid input stream", __func__);
893 return -EINVAL;
894 }
895
896 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
897
898 usecase = get_usecase_from_list(adev, in->usecase);
899
900 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
901 if (ret < 0) {
902 ALOGE("%s Failed to get module id %d", __func__, ret);
903 return ret;
904 }
905 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
906 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
907
908 if(enable)
909 param_value = effect_config.param_value;
910
911 /*Special handling for AEC & NS effects Param values need to be
912 updated if module ids are same*/
913
914 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
915 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
916 if (ret < 0)
917 return ret;
918 }
919
920 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
921
922 return ret;
923}
924
925static void check_and_enable_effect(struct audio_device *adev)
926{
927
928 if (adev->active_input->enable_aec) {
929 enable_disable_effect(adev, EFFECT_AEC, true);
930 }
931
932 if (adev->active_input->enable_ns &&
933 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
934 enable_disable_effect(adev, EFFECT_NS, true);
935 }
936}
937#else
938#define enable_disable_effect(x, y, z) ENOSYS
939#define check_and_enable_effect(x) ENOSYS
940#endif
941
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700942int pcm_ioctl(struct pcm *pcm, int request, ...)
943{
944 va_list ap;
945 void * arg;
946 int pcm_fd = *(int*)pcm;
947
948 va_start(ap, request);
949 arg = va_arg(ap, void *);
950 va_end(ap);
951
952 return ioctl(pcm_fd, request, arg);
953}
954
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700955int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700956 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800957{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700958 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700959 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530960 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800961
962 if (usecase == NULL)
963 return -EINVAL;
964
965 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
966
Surendar Karka93cd25a2018-08-28 14:21:37 +0530967 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700968 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800969 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700970 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800971
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800972#ifdef DS1_DOLBY_DAP_ENABLED
973 audio_extn_dolby_set_dmid(adev);
974 audio_extn_dolby_set_endpoint(adev);
975#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700976 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700977 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530978 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700979 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530980 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530981 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
982 out = usecase->stream.out;
983 if (out && out->compr)
984 audio_extn_utils_compress_set_clk_rec_mode(usecase);
985 }
986
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800987 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700988 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700989 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700990 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800991 ALOGV("%s: exit", __func__);
992 return 0;
993}
994
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700995int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700996 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800997{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700998 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700999 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001000
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301001 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001002 return -EINVAL;
1003
1004 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301005 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001006 snd_device = usecase->in_snd_device;
1007 else
1008 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001009 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001010 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001011 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001012 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001013 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301014 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001015 ALOGV("%s: exit", __func__);
1016 return 0;
1017}
1018
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001019int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001020 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301022 int i, num_devices = 0;
1023 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001024 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1025
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001026 if (snd_device < SND_DEVICE_MIN ||
1027 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001028 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001029 return -EINVAL;
1030 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001031
1032 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001033
1034 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
1035 ALOGE("%s: Invalid sound device returned", __func__);
1036 return -EINVAL;
1037 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001038 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -07001039 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001040 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001041 return 0;
1042 }
1043
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301044
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001045 if (audio_extn_spkr_prot_is_enabled())
1046 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001047
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001048 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1049 audio_extn_spkr_prot_is_enabled()) {
1050 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001051 adev->snd_dev_ref_cnt[snd_device]--;
1052 return -EINVAL;
1053 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001054 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001055 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001056 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001057 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001058 return -EINVAL;
1059 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001060 } else if (platform_split_snd_device(adev->platform,
1061 snd_device,
1062 &num_devices,
1063 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301064 for (i = 0; i < num_devices; i++) {
1065 enable_snd_device(adev, new_snd_devices[i]);
1066 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001067 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001068 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301069
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301070
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301071 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1072 (audio_extn_a2dp_start_playback() < 0)) {
1073 ALOGE(" fail to configure A2dp control path ");
1074 return -EINVAL;
1075 }
1076
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001077 /* due to the possibility of calibration overwrite between listen
1078 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001079 audio_extn_sound_trigger_update_device_status(snd_device,
1080 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301081 audio_extn_listen_update_device_status(snd_device,
1082 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001083 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001084 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001085 audio_extn_sound_trigger_update_device_status(snd_device,
1086 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301087 audio_extn_listen_update_device_status(snd_device,
1088 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001089 return -EINVAL;
1090 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001091 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001092 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301093
1094 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1095 !adev->native_playback_enabled &&
1096 audio_is_true_native_stream_active(adev)) {
1097 ALOGD("%s: %d: napb: enabling native mode in hardware",
1098 __func__, __LINE__);
1099 audio_route_apply_and_update_path(adev->audio_route,
1100 "true-native-mode");
1101 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301102 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301103 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1104 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001105 (audio_extn_ffv_get_stream() == adev->active_input)) {
1106 ALOGD("%s: init ec ref loopback", __func__);
1107 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1108 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001109 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001110 return 0;
1111}
1112
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001113int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001114 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001115{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301116 int i, num_devices = 0;
1117 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001118 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1119
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001120 if (snd_device < SND_DEVICE_MIN ||
1121 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001122 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001123 return -EINVAL;
1124 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001125 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1126 ALOGE("%s: device ref cnt is already 0", __func__);
1127 return -EINVAL;
1128 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001129
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001130 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001131
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001132 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1133 ALOGE("%s: Invalid sound device returned", __func__);
1134 return -EINVAL;
1135 }
1136
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001138 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301139
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001140 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1141 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001142 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001143
1144 // when speaker device is disabled, reset swap.
1145 // will be renabled on usecase start
1146 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001147 } else if (platform_split_snd_device(adev->platform,
1148 snd_device,
1149 &num_devices,
1150 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301151 for (i = 0; i < num_devices; i++) {
1152 disable_snd_device(adev, new_snd_devices[i]);
1153 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001154 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001155 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001156 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001157
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301158 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1159 audio_extn_a2dp_stop_playback();
1160
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001161 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301162 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301163 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1164 adev->native_playback_enabled) {
1165 ALOGD("%s: %d: napb: disabling native mode in hardware",
1166 __func__, __LINE__);
1167 audio_route_reset_and_update_path(adev->audio_route,
1168 "true-native-mode");
1169 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301170 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1171 adev->asrc_mode_enabled) {
1172 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301173 disable_asrc_mode(adev);
1174 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301175 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001176 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1177 (audio_extn_ffv_get_stream() == adev->active_input)) {
1178 ALOGD("%s: deinit ec ref loopback", __func__);
1179 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1180 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001181 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001182 audio_extn_sound_trigger_update_device_status(snd_device,
1183 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301184 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001185 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001186 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001188 return 0;
1189}
1190
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001191/*
1192 legend:
1193 uc - existing usecase
1194 new_uc - new usecase
1195 d1, d11, d2 - SND_DEVICE enums
1196 a1, a2 - corresponding ANDROID device enums
1197 B1, B2 - backend strings
1198
1199case 1
1200 uc->dev d1 (a1) B1
1201 new_uc->dev d1 (a1), d2 (a2) B1, B2
1202
1203 resolution: disable and enable uc->dev on d1
1204
1205case 2
1206 uc->dev d1 (a1) B1
1207 new_uc->dev d11 (a1) B1
1208
1209 resolution: need to switch uc since d1 and d11 are related
1210 (e.g. speaker and voice-speaker)
1211 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1212
1213case 3
1214 uc->dev d1 (a1) B1
1215 new_uc->dev d2 (a2) B2
1216
1217 resolution: no need to switch uc
1218
1219case 4
1220 uc->dev d1 (a1) B1
1221 new_uc->dev d2 (a2) B1
1222
1223 resolution: disable enable uc-dev on d2 since backends match
1224 we cannot enable two streams on two different devices if they
1225 share the same backend. e.g. if offload is on speaker device using
1226 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1227 using the same backend, offload must also be switched to voice-handset.
1228
1229case 5
1230 uc->dev d1 (a1) B1
1231 new_uc->dev d1 (a1), d2 (a2) B1
1232
1233 resolution: disable enable uc-dev on d2 since backends match
1234 we cannot enable two streams on two different devices if they
1235 share the same backend.
1236
1237case 6
1238 uc->dev d1 (a1) B1
1239 new_uc->dev d2 (a1) B2
1240
1241 resolution: no need to switch
1242
1243case 7
1244 uc->dev d1 (a1), d2 (a2) B1, B2
1245 new_uc->dev d1 (a1) B1
1246
1247 resolution: no need to switch
1248
1249*/
1250static snd_device_t derive_playback_snd_device(void * platform,
1251 struct audio_usecase *uc,
1252 struct audio_usecase *new_uc,
1253 snd_device_t new_snd_device)
1254{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301255 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001256
1257 snd_device_t d1 = uc->out_snd_device;
1258 snd_device_t d2 = new_snd_device;
1259
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301260 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301261 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301262 a1 = uc->stream.inout->out_config.devices;
1263 a2 = new_uc->stream.inout->out_config.devices;
1264 break;
1265 default :
1266 a1 = uc->stream.out->devices;
1267 a2 = new_uc->stream.out->devices;
1268 break;
1269 }
1270
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001271 // Treat as a special case when a1 and a2 are not disjoint
1272 if ((a1 != a2) && (a1 & a2)) {
1273 snd_device_t d3[2];
1274 int num_devices = 0;
1275 int ret = platform_split_snd_device(platform,
1276 popcount(a1) > 1 ? d1 : d2,
1277 &num_devices,
1278 d3);
1279 if (ret < 0) {
1280 if (ret != -ENOSYS) {
1281 ALOGW("%s failed to split snd_device %d",
1282 __func__,
1283 popcount(a1) > 1 ? d1 : d2);
1284 }
1285 goto end;
1286 }
1287
1288 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1289 // But if it does happen, we need to give priority to d2 if
1290 // the combo devices active on the existing usecase share a backend.
1291 // This is because we cannot have a usecase active on a combo device
1292 // and a new usecase requests one device in this combo pair.
1293 if (platform_check_backends_match(d3[0], d3[1])) {
1294 return d2; // case 5
1295 } else {
1296 return d1; // case 1
1297 }
1298 } else {
1299 if (platform_check_backends_match(d1, d2)) {
1300 return d2; // case 2, 4
1301 } else {
1302 return d1; // case 6, 3
1303 }
1304 }
1305
1306end:
1307 return d2; // return whatever was calculated before.
1308}
1309
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001310static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301311 struct audio_usecase *uc_info,
1312 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001313{
1314 struct listnode *node;
1315 struct audio_usecase *usecase;
1316 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301317 snd_device_t uc_derive_snd_device;
1318 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001319 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001320 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301321 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001322 /*
1323 * This function is to make sure that all the usecases that are active on
1324 * the hardware codec backend are always routed to any one device that is
1325 * handled by the hardware codec.
1326 * For example, if low-latency and deep-buffer usecases are currently active
1327 * on speaker and out_set_parameters(headset) is received on low-latency
1328 * output, then we have to make sure deep-buffer is also switched to headset,
1329 * because of the limitation that both the devices cannot be enabled
1330 * at the same time as they share the same backend.
1331 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001332 /*
1333 * This call is to check if we need to force routing for a particular stream
1334 * If there is a backend configuration change for the device when a
1335 * new stream starts, then ADM needs to be closed and re-opened with the new
1336 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001337 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001338 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001339 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1340 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301341 /* For a2dp device reconfigure all active sessions
1342 * with new AFE encoder format based on a2dp state
1343 */
1344 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1345 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1346 audio_extn_a2dp_is_force_device_switch()) {
1347 force_routing = true;
1348 force_restart_session = true;
1349 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301350 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1351
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001352 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001353 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001354 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001355 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1356 switch_device[i] = false;
1357
1358 list_for_each(node, &adev->usecase_list) {
1359 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001360
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301361 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1362 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301363 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301364 platform_get_snd_device_name(usecase->out_snd_device),
1365 platform_check_backends_match(snd_device, usecase->out_snd_device));
kunleizef820832018-08-10 11:08:03 +08001366 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301367 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1368 usecase, uc_info, snd_device);
1369 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1370 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1371 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1372 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1373 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1374 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1375 ((force_restart_session) ||
1376 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301377 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1378 __func__, use_case_table[usecase->id],
1379 platform_get_snd_device_name(usecase->out_snd_device));
1380 disable_audio_route(adev, usecase);
1381 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301382 /* Enable existing usecase on derived playback device */
1383 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301384 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301385 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001386 }
1387 }
1388
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301389 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1390 num_uc_to_switch);
1391
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001392 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001393 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001394
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301395 /* Make sure the previous devices to be disabled first and then enable the
1396 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001397 list_for_each(node, &adev->usecase_list) {
1398 usecase = node_to_item(node, struct audio_usecase, list);
1399 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001400 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001401 }
1402 }
1403
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001404 list_for_each(node, &adev->usecase_list) {
1405 usecase = node_to_item(node, struct audio_usecase, list);
1406 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301407 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001408 }
1409 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001410
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001411 /* Re-route all the usecases on the shared backend other than the
1412 specified usecase to new snd devices */
1413 list_for_each(node, &adev->usecase_list) {
1414 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301415 /* Update the out_snd_device only before enabling the audio route */
1416 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301417 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301418 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301419 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301420 use_case_table[usecase->id],
1421 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001422 /* Update voc calibration before enabling VoIP route */
1423 if (usecase->type == VOIP_CALL)
1424 status = platform_switch_voice_call_device_post(adev->platform,
1425 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001426 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301427 enable_audio_route(adev, usecase);
kunleizcf983df2018-03-19 16:28:09 +08001428 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1429 out_set_voip_volume(&usecase->stream.out->stream,
1430 usecase->stream.out->volume_l,
1431 usecase->stream.out->volume_r);
1432 }
Yidong Huang7939a3b2018-01-23 17:32:30 +08001433 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1434 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1435 if (parms)
1436 audio_extn_fm_set_parameters(adev, parms);
1437 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301438 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001439 }
1440 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001441 }
1442}
1443
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301444static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001445 struct audio_usecase *uc_info,
1446 snd_device_t snd_device)
1447{
1448 struct listnode *node;
1449 struct audio_usecase *usecase;
1450 bool switch_device[AUDIO_USECASE_MAX];
1451 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301452 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001453 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001454
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301455 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1456 snd_device);
1457 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301458
1459 /*
1460 * Make sure out devices is checked against out codec backend device and
1461 * also in devices against in codec backend. Checking out device against in
1462 * codec backend or vice versa causes issues.
1463 */
1464 if (uc_info->type == PCM_CAPTURE)
1465 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001466 /*
1467 * This function is to make sure that all the active capture usecases
1468 * are always routed to the same input sound device.
1469 * For example, if audio-record and voice-call usecases are currently
1470 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1471 * is received for voice call then we have to make sure that audio-record
1472 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1473 * because of the limitation that two devices cannot be enabled
1474 * at the same time if they share the same backend.
1475 */
1476 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1477 switch_device[i] = false;
1478
1479 list_for_each(node, &adev->usecase_list) {
1480 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301481 /*
1482 * TODO: Enhance below condition to handle BT sco/USB multi recording
1483 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001484 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001485 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301486 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301487 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301488 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301489 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001490 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001491 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1492 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001493 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001494 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001495 switch_device[usecase->id] = true;
1496 num_uc_to_switch++;
1497 }
1498 }
1499
1500 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001501 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001502
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301503 /* Make sure the previous devices to be disabled first and then enable the
1504 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001505 list_for_each(node, &adev->usecase_list) {
1506 usecase = node_to_item(node, struct audio_usecase, list);
1507 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001508 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001509 }
1510 }
1511
1512 list_for_each(node, &adev->usecase_list) {
1513 usecase = node_to_item(node, struct audio_usecase, list);
1514 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001515 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001516 }
1517 }
1518
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001519 /* Re-route all the usecases on the shared backend other than the
1520 specified usecase to new snd devices */
1521 list_for_each(node, &adev->usecase_list) {
1522 usecase = node_to_item(node, struct audio_usecase, list);
1523 /* Update the in_snd_device only before enabling the audio route */
1524 if (switch_device[usecase->id] ) {
1525 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001526 if (usecase->type != VOICE_CALL) {
1527 /* Update voc calibration before enabling VoIP route */
1528 if (usecase->type == VOIP_CALL)
1529 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001530 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001531 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301532 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001533 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001534 }
1535 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001536 }
1537}
1538
Mingming Yin3a941d42016-02-17 18:08:05 -08001539static void reset_hdmi_sink_caps(struct stream_out *out) {
1540 int i = 0;
1541
1542 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1543 out->supported_channel_masks[i] = 0;
1544 }
1545 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1546 out->supported_formats[i] = 0;
1547 }
1548 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1549 out->supported_sample_rates[i] = 0;
1550 }
1551}
1552
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001554static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001555{
Mingming Yin3a941d42016-02-17 18:08:05 -08001556 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001557 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001558
Mingming Yin3a941d42016-02-17 18:08:05 -08001559 reset_hdmi_sink_caps(out);
1560
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001561 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001562 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001563 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001564 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001565 }
1566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001568 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001569 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001570 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001571 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1572 case 6:
1573 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1574 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1575 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1576 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1577 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1578 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579 break;
1580 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001581 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001582 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583 break;
1584 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001585
1586 // check channel format caps
1587 i = 0;
1588 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1589 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1590 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1591 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1592 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1593 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1594 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1595 }
1596
Ben Romberger1aaaf862017-04-06 17:49:46 -07001597 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1598 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1599 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1600 }
1601
Mingming Yin3a941d42016-02-17 18:08:05 -08001602 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1603 ALOGV(":%s HDMI supports DTS format", __func__);
1604 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1605 }
1606
1607 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1608 ALOGV(":%s HDMI supports DTS HD format", __func__);
1609 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1610 }
1611
Naresh Tanniru928f0862017-04-07 16:44:23 -07001612 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1613 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1614 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1615 }
1616
Mingming Yin3a941d42016-02-17 18:08:05 -08001617
1618 // check sample rate caps
1619 i = 0;
1620 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1621 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1622 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1623 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1624 }
1625 }
1626
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001627 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001628}
1629
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001630static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1631 uint32_t *supported_sample_rates __unused,
1632 uint32_t max_rates __unused)
1633{
1634 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1635 supported_sample_rates,
1636 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301637 ssize_t i = 0;
1638
1639 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001640 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1641 supported_sample_rates[i]);
1642 }
1643 return count;
1644}
1645
1646static inline int read_usb_sup_channel_masks(bool is_playback,
1647 audio_channel_mask_t *supported_channel_masks,
1648 uint32_t max_masks)
1649{
1650 int channels = audio_extn_usb_get_max_channels(is_playback);
1651 int channel_count;
1652 uint32_t num_masks = 0;
1653 if (channels > MAX_HIFI_CHANNEL_COUNT)
1654 channels = MAX_HIFI_CHANNEL_COUNT;
1655
1656 if (is_playback) {
1657 // For playback we never report mono because the framework always outputs stereo
1658 channel_count = DEFAULT_CHANNEL_COUNT;
1659 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1660 // above 2 but we want indexed masks here. So we
1661 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1662 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1663 }
1664 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1665 supported_channel_masks[num_masks++] =
1666 audio_channel_mask_for_index_assignment_from_count(channel_count);
1667 }
1668 } else {
1669 // For capture we report all supported channel masks from 1 channel up.
1670 channel_count = MIN_CHANNEL_COUNT;
1671 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1672 // indexed mask
1673 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1674 supported_channel_masks[num_masks++] =
1675 audio_channel_in_mask_from_count(channel_count);
1676 }
1677 }
1678 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1679 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1680 return num_masks;
1681}
1682
1683static inline int read_usb_sup_formats(bool is_playback __unused,
1684 audio_format_t *supported_formats,
1685 uint32_t max_formats __unused)
1686{
1687 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1688 switch (bitwidth) {
1689 case 24:
1690 // XXX : usb.c returns 24 for s24 and s24_le?
1691 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1692 break;
1693 case 32:
1694 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1695 break;
1696 case 16:
1697 default :
1698 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1699 break;
1700 }
1701 ALOGV("%s: %s supported format %d", __func__,
1702 is_playback ? "P" : "C", bitwidth);
1703 return 1;
1704}
1705
1706static inline int read_usb_sup_params_and_compare(bool is_playback,
1707 audio_format_t *format,
1708 audio_format_t *supported_formats,
1709 uint32_t max_formats,
1710 audio_channel_mask_t *mask,
1711 audio_channel_mask_t *supported_channel_masks,
1712 uint32_t max_masks,
1713 uint32_t *rate,
1714 uint32_t *supported_sample_rates,
1715 uint32_t max_rates) {
1716 int ret = 0;
1717 int num_formats;
1718 int num_masks;
1719 int num_rates;
1720 int i;
1721
1722 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1723 max_formats);
1724 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1725 max_masks);
1726
1727 num_rates = read_usb_sup_sample_rates(is_playback,
1728 supported_sample_rates, max_rates);
1729
1730#define LUT(table, len, what, dflt) \
1731 for (i=0; i<len && (table[i] != what); i++); \
1732 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1733
1734 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1735 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1736 LUT(supported_sample_rates, num_rates, *rate, 0);
1737
1738#undef LUT
1739 return ret < 0 ? -EINVAL : 0; // HACK TBD
1740}
1741
Alexy Josephb1379942016-01-29 15:49:38 -08001742audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001743 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001744{
1745 struct audio_usecase *usecase;
1746 struct listnode *node;
1747
1748 list_for_each(node, &adev->usecase_list) {
1749 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001750 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001751 ALOGV("%s: usecase id %d", __func__, usecase->id);
1752 return usecase->id;
1753 }
1754 }
1755 return USECASE_INVALID;
1756}
1757
Alexy Josephb1379942016-01-29 15:49:38 -08001758struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001759 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001760{
1761 struct audio_usecase *usecase;
1762 struct listnode *node;
1763
1764 list_for_each(node, &adev->usecase_list) {
1765 usecase = node_to_item(node, struct audio_usecase, list);
1766 if (usecase->id == uc_id)
1767 return usecase;
1768 }
1769 return NULL;
1770}
1771
Dhananjay Kumard4833242016-10-06 22:09:12 +05301772struct stream_in *get_next_active_input(const struct audio_device *adev)
1773{
1774 struct audio_usecase *usecase;
1775 struct listnode *node;
1776
1777 list_for_each_reverse(node, &adev->usecase_list) {
1778 usecase = node_to_item(node, struct audio_usecase, list);
1779 if (usecase->type == PCM_CAPTURE)
1780 return usecase->stream.in;
1781 }
1782 return NULL;
1783}
1784
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301785/*
1786 * is a true native playback active
1787 */
1788bool audio_is_true_native_stream_active(struct audio_device *adev)
1789{
1790 bool active = false;
1791 int i = 0;
1792 struct listnode *node;
1793
1794 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1795 ALOGV("%s:napb: not in true mode or non hdphones device",
1796 __func__);
1797 active = false;
1798 goto exit;
1799 }
1800
1801 list_for_each(node, &adev->usecase_list) {
1802 struct audio_usecase *uc;
1803 uc = node_to_item(node, struct audio_usecase, list);
1804 struct stream_out *curr_out =
1805 (struct stream_out*) uc->stream.out;
1806
1807 if (curr_out && PCM_PLAYBACK == uc->type) {
1808 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1809 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1810 uc->id, curr_out->sample_rate,
1811 curr_out->bit_width,
1812 platform_get_snd_device_name(uc->out_snd_device));
1813
1814 if (is_offload_usecase(uc->id) &&
1815 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1816 active = true;
1817 ALOGD("%s:napb:native stream detected", __func__);
1818 }
1819 }
1820 }
1821exit:
1822 return active;
1823}
1824
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001825uint32_t adev_get_dsp_bit_width_enforce_mode()
1826{
1827 if (adev == NULL) {
1828 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1829 return 0;
1830 }
1831 return adev->dsp_bit_width_enforce_mode;
1832}
1833
1834static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1835{
1836 char value[PROPERTY_VALUE_MAX];
1837 int trial;
1838 uint32_t dsp_bit_width_enforce_mode = 0;
1839
1840 if (!mixer) {
1841 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1842 __func__);
1843 return 0;
1844 }
1845
1846 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1847 value, NULL) > 0) {
1848 trial = atoi(value);
1849 switch (trial) {
1850 case 16:
1851 dsp_bit_width_enforce_mode = 16;
1852 break;
1853 case 24:
1854 dsp_bit_width_enforce_mode = 24;
1855 break;
1856 case 32:
1857 dsp_bit_width_enforce_mode = 32;
1858 break;
1859 default:
1860 dsp_bit_width_enforce_mode = 0;
1861 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1862 break;
1863 }
1864 }
1865
1866 return dsp_bit_width_enforce_mode;
1867}
1868
1869static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1870 uint32_t enforce_mode,
1871 bool enable)
1872{
1873 struct mixer_ctl *ctl = NULL;
1874 const char *mixer_ctl_name = "ASM Bit Width";
1875 uint32_t asm_bit_width_mode = 0;
1876
1877 if (enforce_mode == 0) {
1878 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1879 return;
1880 }
1881
1882 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1883 if (!ctl) {
1884 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1885 __func__, mixer_ctl_name);
1886 return;
1887 }
1888
1889 if (enable)
1890 asm_bit_width_mode = enforce_mode;
1891 else
1892 asm_bit_width_mode = 0;
1893
1894 ALOGV("%s DSP bit width feature status is %d width=%d",
1895 __func__, enable, asm_bit_width_mode);
1896 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1897 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1898 asm_bit_width_mode);
1899
1900 return;
1901}
1902
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301903/*
1904 * if native DSD playback active
1905 */
1906bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1907{
1908 bool active = false;
1909 struct listnode *node = NULL;
1910 struct audio_usecase *uc = NULL;
1911 struct stream_out *curr_out = NULL;
1912
1913 list_for_each(node, &adev->usecase_list) {
1914 uc = node_to_item(node, struct audio_usecase, list);
1915 curr_out = (struct stream_out*) uc->stream.out;
1916
1917 if (curr_out && PCM_PLAYBACK == uc->type &&
1918 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1919 active = true;
1920 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301921 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301922 }
1923 }
1924 return active;
1925}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301926
1927static bool force_device_switch(struct audio_usecase *usecase)
1928{
1929 bool ret = false;
1930 bool is_it_true_mode = false;
1931
Zhou Song30f2c3e2018-02-08 14:02:15 +08001932 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05301933 usecase->type == TRANSCODE_LOOPBACK_RX ||
1934 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08001935 return false;
1936 }
1937
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001938 if(usecase->stream.out == NULL) {
1939 ALOGE("%s: stream.out is NULL", __func__);
1940 return false;
1941 }
1942
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301943 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001944 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1945 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1946 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301947 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1948 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1949 (!is_it_true_mode && adev->native_playback_enabled)){
1950 ret = true;
1951 ALOGD("napb: time to toggle native mode");
1952 }
1953 }
1954
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301955 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301956 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1957 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001958 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301959 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301960 ALOGD("Force a2dp device switch to update new encoder config");
1961 ret = true;
1962 }
1963
Manish Dewangan671a4202017-08-18 17:30:46 +05301964 if (usecase->stream.out->stream_config_changed) {
1965 ALOGD("Force stream_config_changed to update iec61937 transmission config");
1966 return true;
1967 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301968 return ret;
1969}
1970
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301971bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1972{
1973 bool ret=false;
1974 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1975 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1976 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1977 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1978 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1979 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1980 ret = true;
1981
1982 return ret;
1983}
1984
1985bool is_a2dp_device(snd_device_t out_snd_device)
1986{
1987 bool ret=false;
1988 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1989 ret = true;
1990
1991 return ret;
1992}
1993
1994bool is_bt_soc_on(struct audio_device *adev)
1995{
1996 struct mixer_ctl *ctl;
1997 char *mixer_ctl_name = "BT SOC status";
1998 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1999 bool bt_soc_status = true;
2000 if (!ctl) {
2001 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2002 __func__, mixer_ctl_name);
2003 /*This is to ensure we dont break targets which dont have the kernel change*/
2004 return true;
2005 }
2006 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2007 ALOGD("BT SOC status: %d",bt_soc_status);
2008 return bt_soc_status;
2009}
2010
2011int out_standby_l(struct audio_stream *stream);
2012
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002013int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002014{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002015 snd_device_t out_snd_device = SND_DEVICE_NONE;
2016 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002017 struct audio_usecase *usecase = NULL;
2018 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002019 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002020 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302021 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002022 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002023 int status = 0;
Weiyin Jiang7991be92018-02-01 17:24:33 +08002024 audio_devices_t audio_device;
2025 audio_channel_mask_t channel_mask;
2026 int sample_rate;
2027 int acdb_id;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302029 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2030
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002031 usecase = get_usecase_from_list(adev, uc_id);
2032 if (usecase == NULL) {
2033 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2034 return -EINVAL;
2035 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002036
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002037 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002038 (usecase->type == VOIP_CALL) ||
2039 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302040 if(usecase->stream.out == NULL) {
2041 ALOGE("%s: stream.out is NULL", __func__);
2042 return -EINVAL;
2043 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002044 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002045 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002046 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002047 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302048 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302049 if (usecase->stream.inout == NULL) {
2050 ALOGE("%s: stream.inout is NULL", __func__);
2051 return -EINVAL;
2052 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302053 stream_out.devices = usecase->stream.inout->out_config.devices;
2054 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2055 stream_out.format = usecase->stream.inout->out_config.format;
2056 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2057 out_snd_device = platform_get_output_snd_device(adev->platform,
2058 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302059 usecase->devices = out_snd_device;
2060 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2061 if (usecase->stream.inout == NULL) {
2062 ALOGE("%s: stream.inout is NULL", __func__);
2063 return -EINVAL;
2064 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302065 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302066 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002067 } else {
2068 /*
2069 * If the voice call is active, use the sound devices of voice call usecase
2070 * so that it would not result any device switch. All the usecases will
2071 * be switched to new device when select_devices() is called for voice call
2072 * usecase. This is to avoid switching devices for voice call when
2073 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002074 * choose voice call device only if the use case device is
2075 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002076 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002077 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002078 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002079 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002080 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2081 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302082 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2083 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002084 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002085 in_snd_device = vc_usecase->in_snd_device;
2086 out_snd_device = vc_usecase->out_snd_device;
2087 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002088 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002089 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002090 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002091 if ((voip_usecase != NULL) &&
2092 (usecase->type == PCM_PLAYBACK) &&
2093 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002094 out_snd_device_backend_match = platform_check_backends_match(
2095 voip_usecase->out_snd_device,
2096 platform_get_output_snd_device(
2097 adev->platform,
2098 usecase->stream.out));
2099 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002100 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002101 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2102 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002103 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002104 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002105 in_snd_device = voip_usecase->in_snd_device;
2106 out_snd_device = voip_usecase->out_snd_device;
2107 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002108 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002109 hfp_ucid = audio_extn_hfp_get_usecase();
2110 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002111 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002112 in_snd_device = hfp_usecase->in_snd_device;
2113 out_snd_device = hfp_usecase->out_snd_device;
2114 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002115 }
2116 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302117 if (usecase->stream.out == NULL) {
2118 ALOGE("%s: stream.out is NULL", __func__);
2119 return -EINVAL;
2120 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002121 usecase->devices = usecase->stream.out->devices;
2122 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002123 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002124 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002125 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002126 if (usecase->stream.out == adev->primary_output &&
2127 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08002128 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002129 select_devices(adev, adev->active_input->usecase);
2130 }
2131 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002132 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302133 if (usecase->stream.in == NULL) {
2134 ALOGE("%s: stream.in is NULL", __func__);
2135 return -EINVAL;
2136 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002137 usecase->devices = usecase->stream.in->device;
2138 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002139 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002140 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002141 if (adev->active_input &&
2142 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302143 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
2144 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
2145 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002146 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002147 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002148 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2149 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002150 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002151 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002152 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002153 }
2154 }
2155
2156 if (out_snd_device == usecase->out_snd_device &&
2157 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302158
2159 if (!force_device_switch(usecase))
2160 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161 }
2162
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302163 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
2164 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
2165 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2166 return 0;
2167 }
2168
sangwoobc677242013-08-08 16:53:43 +09002169 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07002170 out_snd_device, platform_get_snd_device_name(out_snd_device),
2171 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002172
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002173 /*
2174 * Limitation: While in call, to do a device switch we need to disable
2175 * and enable both RX and TX devices though one of them is same as current
2176 * device.
2177 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002178 if ((usecase->type == VOICE_CALL) &&
2179 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2180 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002181 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002182 }
2183
2184 if (((usecase->type == VOICE_CALL) ||
2185 (usecase->type == VOIP_CALL)) &&
2186 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2187 /* Disable sidetone only if voice/voip call already exists */
2188 if (voice_is_call_state_active(adev) ||
2189 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002190 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002191
2192 /* Disable aanc only if voice call exists */
2193 if (voice_is_call_state_active(adev))
2194 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002195 }
2196
Zhou Songc66eb7e2017-08-08 18:29:07 +08002197 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302198 (!audio_extn_a2dp_is_ready())) {
2199 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002200 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302201 }
2202
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002203 /* Disable current sound devices */
2204 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002205 disable_audio_route(adev, usecase);
2206 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207 }
2208
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002209 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002210 disable_audio_route(adev, usecase);
2211 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212 }
2213
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002214 /* Applicable only on the targets that has external modem.
2215 * New device information should be sent to modem before enabling
2216 * the devices to reduce in-call device switch time.
2217 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002218 if ((usecase->type == VOICE_CALL) &&
2219 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2220 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002221 status = platform_switch_voice_call_enable_device_config(adev->platform,
2222 out_snd_device,
2223 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002224 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002225
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002226 /* Enable new sound devices */
2227 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002228 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302229 if (platform_check_codec_asrc_support(adev->platform))
2230 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002231 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002232 }
2233
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002234 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302235 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002236 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002237 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002238
Avinash Vaish71a8b972014-07-24 15:36:33 +05302239 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002240 status = platform_switch_voice_call_device_post(adev->platform,
2241 out_snd_device,
2242 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302243 enable_audio_route_for_voice_usecases(adev, usecase);
2244 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002245
sangwoo170731f2013-06-08 15:36:36 +09002246 usecase->in_snd_device = in_snd_device;
2247 usecase->out_snd_device = out_snd_device;
2248
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302249 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2250 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302251 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002252 if ((24 == usecase->stream.out->bit_width) &&
2253 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2254 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2255 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2256 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2257 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2258 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2259 /*
2260 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2261 * configured device sample rate, if not update the COPP rate to be equal to the
2262 * device sample rate, else open COPP at stream sample rate
2263 */
2264 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2265 usecase->stream.out->sample_rate,
2266 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302267 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2268 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002269 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2270 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2271 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2272 }
2273
Weiyin Jiang7991be92018-02-01 17:24:33 +08002274 /* Cache stream information to be notified to gef clients */
2275 audio_device = usecase->stream.out->devices;
2276 channel_mask = usecase->stream.out->channel_mask;
2277 sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
2278 acdb_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302279 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002280 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002281
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002282 /* If input stream is already running then effect needs to be
2283 applied on the new input device that's being enabled here. */
2284 if ((in_snd_device != SND_DEVICE_NONE) && (!adev->active_input->standby))
2285 check_and_enable_effect(adev);
2286
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002287 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002288 /* Enable aanc only if voice call exists */
2289 if (voice_is_call_state_active(adev))
2290 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2291
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002292 /* Enable sidetone only if other voice/voip call already exists */
2293 if (voice_is_call_state_active(adev) ||
2294 voice_extn_compress_voip_is_started(adev))
2295 voice_set_sidetone(adev, out_snd_device, true);
2296 }
2297
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002298 /* Applicable only on the targets that has external modem.
2299 * Enable device command should be sent to modem only after
2300 * enabling voice call mixer controls
2301 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002302 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002303 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2304 out_snd_device,
2305 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302306
2307 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2308
2309 if (usecase->type == VOIP_CALL) {
2310 if (adev->active_input != NULL &&
2311 !adev->active_input->standby) {
2312 if (is_bt_soc_on(adev) == false){
2313 ALOGD("BT SCO MIC disconnected while in connection");
2314 if (adev->active_input->pcm != NULL)
2315 pcm_stop(adev->active_input->pcm);
2316 }
2317 }
2318 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2319 && usecase->stream.out->started) {
2320 if (is_bt_soc_on(adev) == false) {
2321 ALOGD("BT SCO/A2DP disconnected while in connection");
2322 out_standby_l(&usecase->stream.out->stream.common);
2323 }
2324 }
2325 } else if ((usecase->stream.out != NULL) &&
2326 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2327 usecase->stream.out->started) {
2328 if (is_bt_soc_on(adev) == false) {
2329 ALOGD("BT SCO/A2dp disconnected while in connection");
2330 out_standby_l(&usecase->stream.out->stream.common);
2331 }
2332 }
2333 }
2334
Weiyin Jiang7991be92018-02-01 17:24:33 +08002335 /* Notify device change info to effect clients registered
2336 * NOTE: device lock has to be unlock temporarily here.
2337 * To the worst case, we notify stale info to clients.
2338 */
2339 if (usecase->type == PCM_PLAYBACK) {
2340 pthread_mutex_unlock(&adev->lock);
2341 audio_extn_gef_notify_device_config(audio_device, channel_mask, sample_rate, acdb_id);
2342 pthread_mutex_lock(&adev->lock);
2343 }
2344
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302345 ALOGD("%s: done",__func__);
2346
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347 return status;
2348}
2349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350static int stop_input_stream(struct stream_in *in)
2351{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302352 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302354
2355 if (in == NULL) {
2356 ALOGE("%s: stream_in ptr is NULL", __func__);
2357 return -EINVAL;
2358 }
2359
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360 struct audio_device *adev = in->dev;
2361
Eric Laurent994a6932013-07-17 11:51:42 -07002362 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002363 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364 uc_info = get_usecase_from_list(adev, in->usecase);
2365 if (uc_info == NULL) {
2366 ALOGE("%s: Could not find the usecase (%d) in the list",
2367 __func__, in->usecase);
2368 return -EINVAL;
2369 }
2370
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002371 /* Close in-call recording streams */
2372 voice_check_and_stop_incall_rec_usecase(adev, in);
2373
Eric Laurent150dbfe2013-02-27 14:31:02 -08002374 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002375 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002376
2377 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002378 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002379
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002380 list_remove(&uc_info->list);
2381 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002383 adev->active_input = get_next_active_input(adev);
2384
Eric Laurent994a6932013-07-17 11:51:42 -07002385 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386 return ret;
2387}
2388
2389int start_input_stream(struct stream_in *in)
2390{
2391 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002392 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002393 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302394
2395 if (in == NULL) {
2396 ALOGE("%s: stream_in ptr is NULL", __func__);
2397 return -EINVAL;
2398 }
2399
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002400 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002401 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002402 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002403
Mingming Yin2664a5b2015-09-03 10:53:11 -07002404 if (get_usecase_from_list(adev, usecase) == NULL)
2405 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302406 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2407 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002408
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302409 if (CARD_STATUS_OFFLINE == in->card_status||
2410 CARD_STATUS_OFFLINE == adev->card_status) {
2411 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302412 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302413 goto error_config;
2414 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302415
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302416 if (audio_is_bluetooth_sco_device(in->device)) {
2417 if (!adev->bt_sco_on) {
2418 ALOGE("%s: SCO profile is not ready, return error", __func__);
2419 ret = -EIO;
2420 goto error_config;
2421 }
2422 }
2423
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002424 /* Check if source matches incall recording usecase criteria */
2425 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2426 if (ret)
2427 goto error_config;
2428 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002429 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2430
2431 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2432 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2433 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002434 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002435 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002436
Eric Laurentb23d5282013-05-14 15:27:20 -07002437 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438 if (in->pcm_device_id < 0) {
2439 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2440 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002441 ret = -EINVAL;
2442 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002443 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002444
2445 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002446 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002447
2448 if (!uc_info) {
2449 ret = -ENOMEM;
2450 goto error_config;
2451 }
2452
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002453 uc_info->id = in->usecase;
2454 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002455 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002456 uc_info->devices = in->device;
2457 uc_info->in_snd_device = SND_DEVICE_NONE;
2458 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002459
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002460 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302461 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2462 adev->perf_lock_opts,
2463 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002464 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465
Haynes Mathew George16081042017-05-31 17:16:49 -07002466 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302467 ret = audio_extn_cin_start_input_stream(in);
2468 if (ret)
2469 goto error_open;
2470 else
2471 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002472 }
2473
Haynes Mathew George16081042017-05-31 17:16:49 -07002474 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002475 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002476 ALOGE("%s: pcm stream not ready", __func__);
2477 goto error_open;
2478 }
2479 ret = pcm_start(in->pcm);
2480 if (ret < 0) {
2481 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2482 goto error_open;
2483 }
2484 } else {
2485 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2486 unsigned int pcm_open_retry_count = 0;
2487
2488 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2489 flags |= PCM_MMAP | PCM_NOIRQ;
2490 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2491 } else if (in->realtime) {
2492 flags |= PCM_MMAP | PCM_NOIRQ;
2493 }
2494
Garmond Leunge2433c32017-09-28 21:51:22 -07002495 if (audio_extn_ffv_get_stream() == in) {
2496 ALOGD("%s: ffv stream, update pcm config", __func__);
2497 audio_extn_ffv_update_pcm_config(&config);
2498 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002499 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2500 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2501
2502 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002503 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002504 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002505 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002506 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302507 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302508 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2509 adev->card_status = CARD_STATUS_OFFLINE;
2510 in->card_status = CARD_STATUS_OFFLINE;
2511 ret = -EIO;
2512 goto error_open;
2513 }
2514
Haynes Mathew George16081042017-05-31 17:16:49 -07002515 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2516 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2517 if (in->pcm != NULL) {
2518 pcm_close(in->pcm);
2519 in->pcm = NULL;
2520 }
2521 if (pcm_open_retry_count-- == 0) {
2522 ret = -EIO;
2523 goto error_open;
2524 }
2525 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2526 continue;
2527 }
2528 break;
2529 }
2530
2531 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002532 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002533 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002534 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002535 if (ret < 0) {
2536 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2537 pcm_close(in->pcm);
2538 in->pcm = NULL;
2539 goto error_open;
2540 }
2541 register_in_stream(in);
2542 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002543 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002544 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002545 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002546 if (ret < 0) {
2547 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002548 pcm_close(in->pcm);
2549 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002550 goto error_open;
2551 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002552 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002553 }
2554
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002555 check_and_enable_effect(adev);
2556
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302557done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302558 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002559 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002560
Eric Laurentc8400632013-02-14 19:04:54 -08002561 return ret;
2562
2563error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302564 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002566error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302567 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302568 /*
2569 * sleep 50ms to allow sufficient time for kernel
2570 * drivers to recover incases like SSR.
2571 */
2572 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002573 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002574
2575 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576}
2577
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002578void lock_input_stream(struct stream_in *in)
2579{
2580 pthread_mutex_lock(&in->pre_lock);
2581 pthread_mutex_lock(&in->lock);
2582 pthread_mutex_unlock(&in->pre_lock);
2583}
2584
2585void lock_output_stream(struct stream_out *out)
2586{
2587 pthread_mutex_lock(&out->pre_lock);
2588 pthread_mutex_lock(&out->lock);
2589 pthread_mutex_unlock(&out->pre_lock);
2590}
2591
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002592/* must be called with out->lock locked */
2593static int send_offload_cmd_l(struct stream_out* out, int command)
2594{
2595 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2596
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002597 if (!cmd) {
2598 ALOGE("failed to allocate mem for command 0x%x", command);
2599 return -ENOMEM;
2600 }
2601
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002602 ALOGVV("%s %d", __func__, command);
2603
2604 cmd->cmd = command;
2605 list_add_tail(&out->offload_cmd_list, &cmd->node);
2606 pthread_cond_signal(&out->offload_cond);
2607 return 0;
2608}
2609
2610/* must be called iwth out->lock locked */
2611static void stop_compressed_output_l(struct stream_out *out)
2612{
2613 out->offload_state = OFFLOAD_STATE_IDLE;
2614 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002615 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002616 if (out->compr != NULL) {
2617 compress_stop(out->compr);
2618 while (out->offload_thread_blocked) {
2619 pthread_cond_wait(&out->cond, &out->lock);
2620 }
2621 }
2622}
2623
Varun Balaraje49253e2017-07-06 19:48:56 +05302624bool is_interactive_usecase(audio_usecase_t uc_id)
2625{
2626 unsigned int i;
2627 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2628 if (uc_id == interactive_usecases[i])
2629 return true;
2630 }
2631 return false;
2632}
2633
2634static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2635{
2636 audio_usecase_t ret_uc = USECASE_INVALID;
2637 unsigned int intract_uc_index;
2638 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2639
2640 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2641 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2642 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2643 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2644 ret_uc = interactive_usecases[intract_uc_index];
2645 break;
2646 }
2647 }
2648
2649 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2650 return ret_uc;
2651}
2652
2653static void free_interactive_usecase(struct audio_device *adev,
2654 audio_usecase_t uc_id)
2655{
2656 unsigned int interact_uc_index;
2657 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2658
2659 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2660 if (interactive_usecases[interact_uc_index] == uc_id) {
2661 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2662 break;
2663 }
2664 }
2665 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2666}
2667
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002668bool is_offload_usecase(audio_usecase_t uc_id)
2669{
2670 unsigned int i;
2671 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2672 if (uc_id == offload_usecases[i])
2673 return true;
2674 }
2675 return false;
2676}
2677
Dhananjay Kumarac341582017-02-23 23:42:25 +05302678static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002679{
vivek mehta446c3962015-09-14 10:57:35 -07002680 audio_usecase_t ret_uc = USECASE_INVALID;
2681 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002682 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002683 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302684 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002685 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2686 else
2687 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002688
vivek mehta446c3962015-09-14 10:57:35 -07002689 pthread_mutex_lock(&adev->lock);
2690 if (get_usecase_from_list(adev, ret_uc) != NULL)
2691 ret_uc = USECASE_INVALID;
2692 pthread_mutex_unlock(&adev->lock);
2693
2694 return ret_uc;
2695 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002696
2697 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002698 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2699 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2700 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2701 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002702 break;
2703 }
2704 }
vivek mehta446c3962015-09-14 10:57:35 -07002705
2706 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2707 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002708}
2709
2710static void free_offload_usecase(struct audio_device *adev,
2711 audio_usecase_t uc_id)
2712{
vivek mehta446c3962015-09-14 10:57:35 -07002713 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002714 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002715
2716 if (!adev->multi_offload_enable)
2717 return;
2718
2719 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2720 if (offload_usecases[offload_uc_index] == uc_id) {
2721 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002722 break;
2723 }
2724 }
2725 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2726}
2727
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002728static void *offload_thread_loop(void *context)
2729{
2730 struct stream_out *out = (struct stream_out *) context;
2731 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002732 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002733
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002734 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2735 set_sched_policy(0, SP_FOREGROUND);
2736 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2737
2738 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002739 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002740 for (;;) {
2741 struct offload_cmd *cmd = NULL;
2742 stream_callback_event_t event;
2743 bool send_callback = false;
2744
2745 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2746 __func__, list_empty(&out->offload_cmd_list),
2747 out->offload_state);
2748 if (list_empty(&out->offload_cmd_list)) {
2749 ALOGV("%s SLEEPING", __func__);
2750 pthread_cond_wait(&out->offload_cond, &out->lock);
2751 ALOGV("%s RUNNING", __func__);
2752 continue;
2753 }
2754
2755 item = list_head(&out->offload_cmd_list);
2756 cmd = node_to_item(item, struct offload_cmd, node);
2757 list_remove(item);
2758
2759 ALOGVV("%s STATE %d CMD %d out->compr %p",
2760 __func__, out->offload_state, cmd->cmd, out->compr);
2761
2762 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2763 free(cmd);
2764 break;
2765 }
2766
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002767 // allow OFFLOAD_CMD_ERROR reporting during standby
2768 // this is needed to handle failures during compress_open
2769 // Note however that on a pause timeout, the stream is closed
2770 // and no offload usecase will be active. Therefore this
2771 // special case is needed for compress_open failures alone
2772 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2773 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002774 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002775 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002776 pthread_cond_signal(&out->cond);
2777 continue;
2778 }
2779 out->offload_thread_blocked = true;
2780 pthread_mutex_unlock(&out->lock);
2781 send_callback = false;
2782 switch(cmd->cmd) {
2783 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002784 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002785 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002786 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002787 send_callback = true;
2788 event = STREAM_CBK_EVENT_WRITE_READY;
2789 break;
2790 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002791 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302792 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002793 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302794 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002795 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302796 if (ret < 0)
2797 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302798 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302799 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002800 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002801 else
2802 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002803 if (-ENETRESET != ret && !(-EINTR == ret &&
2804 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302805 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302806 pthread_mutex_lock(&out->lock);
2807 out->send_new_metadata = 1;
2808 out->send_next_track_params = true;
2809 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302810 event = STREAM_CBK_EVENT_DRAIN_READY;
2811 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2812 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302813 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002814 break;
2815 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002816 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002817 ret = compress_drain(out->compr);
2818 ALOGD("copl(%p):out of compress_drain", out);
2819 // EINTR check avoids drain interruption due to SSR
2820 if (-ENETRESET != ret && !(-EINTR == ret &&
2821 CARD_STATUS_OFFLINE == out->card_status)) {
2822 send_callback = true;
2823 event = STREAM_CBK_EVENT_DRAIN_READY;
2824 } else
2825 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002826 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302827 case OFFLOAD_CMD_ERROR:
2828 ALOGD("copl(%p): sending error callback to AF", out);
2829 send_callback = true;
2830 event = STREAM_CBK_EVENT_ERROR;
2831 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002832 default:
2833 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2834 break;
2835 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002836 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002837 out->offload_thread_blocked = false;
2838 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002839 if (send_callback && out->client_callback) {
2840 ALOGVV("%s: sending client_callback event %d", __func__, event);
2841 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002842 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002843 free(cmd);
2844 }
2845
2846 pthread_cond_signal(&out->cond);
2847 while (!list_empty(&out->offload_cmd_list)) {
2848 item = list_head(&out->offload_cmd_list);
2849 list_remove(item);
2850 free(node_to_item(item, struct offload_cmd, node));
2851 }
2852 pthread_mutex_unlock(&out->lock);
2853
2854 return NULL;
2855}
2856
2857static int create_offload_callback_thread(struct stream_out *out)
2858{
2859 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2860 list_init(&out->offload_cmd_list);
2861 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2862 offload_thread_loop, out);
2863 return 0;
2864}
2865
2866static int destroy_offload_callback_thread(struct stream_out *out)
2867{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002868 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002869 stop_compressed_output_l(out);
2870 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2871
2872 pthread_mutex_unlock(&out->lock);
2873 pthread_join(out->offload_thread, (void **) NULL);
2874 pthread_cond_destroy(&out->offload_cond);
2875
2876 return 0;
2877}
2878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879static int stop_output_stream(struct stream_out *out)
2880{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302881 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882 struct audio_usecase *uc_info;
2883 struct audio_device *adev = out->dev;
2884
Eric Laurent994a6932013-07-17 11:51:42 -07002885 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002886 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887 uc_info = get_usecase_from_list(adev, out->usecase);
2888 if (uc_info == NULL) {
2889 ALOGE("%s: Could not find the usecase (%d) in the list",
2890 __func__, out->usecase);
2891 return -EINVAL;
2892 }
2893
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002894 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302895 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002896 if (adev->visualizer_stop_output != NULL)
2897 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002898
2899 audio_extn_dts_remove_state_notifier_node(out->usecase);
2900
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002901 if (adev->offload_effects_stop_output != NULL)
2902 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2903 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002904
Eric Laurent150dbfe2013-02-27 14:31:02 -08002905 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002906 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002907
2908 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002909 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002910
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002911 if (is_offload_usecase(out->usecase)) {
2912 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2913 adev->dsp_bit_width_enforce_mode,
2914 false);
2915 }
2916
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002917 list_remove(&uc_info->list);
2918 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302919 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002920 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302921 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002922 ALOGV("Disable passthrough , reset mixer to pcm");
2923 /* NO_PASSTHROUGH */
2924 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002925 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002926 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2927 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002928
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302929 /* Must be called after removing the usecase from list */
2930 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05302931 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302932
Manish Dewangan21a850a2017-08-14 12:03:55 +05302933 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002934 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2935 if (ret < 0)
2936 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2937 }
2938
Eric Laurent994a6932013-07-17 11:51:42 -07002939 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002940 return ret;
2941}
2942
2943int start_output_stream(struct stream_out *out)
2944{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002945 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946 struct audio_usecase *uc_info;
2947 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002948 char mixer_ctl_name[128];
2949 struct mixer_ctl *ctl = NULL;
2950 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302951 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002952
Haynes Mathew George380745d2017-10-04 15:27:45 -07002953 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002954 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2955 ret = -EINVAL;
2956 goto error_config;
2957 }
2958
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302959 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2960 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2961 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302962
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302963 if (CARD_STATUS_OFFLINE == out->card_status ||
2964 CARD_STATUS_OFFLINE == adev->card_status) {
2965 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302966 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302967 goto error_config;
2968 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302969
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302970 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2971 if (!audio_extn_a2dp_is_ready()) {
2972 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302973 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302974 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302975 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2976 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2977 ret = -EAGAIN;
2978 goto error_config;
2979 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302980 }
2981 }
2982 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302983 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2984 if (!adev->bt_sco_on) {
2985 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2986 //combo usecase just by pass a2dp
2987 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
2988 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2989 } else {
2990 ALOGE("%s: SCO profile is not ready, return error", __func__);
2991 ret = -EAGAIN;
2992 goto error_config;
2993 }
2994 }
2995 }
2996
Eric Laurentb23d5282013-05-14 15:27:20 -07002997 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998 if (out->pcm_device_id < 0) {
2999 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3000 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003001 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003002 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003 }
3004
3005 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003006
3007 if (!uc_info) {
3008 ret = -ENOMEM;
3009 goto error_config;
3010 }
3011
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012 uc_info->id = out->usecase;
3013 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003014 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003015 uc_info->devices = out->devices;
3016 uc_info->in_snd_device = SND_DEVICE_NONE;
3017 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003018 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303020 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3021 adev->perf_lock_opts,
3022 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303023
3024 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303025 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303026 if (audio_extn_passthru_is_enabled() &&
3027 audio_extn_passthru_is_passthrough_stream(out)) {
3028 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303029 }
3030 }
3031
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303032 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3033 (!audio_extn_a2dp_is_ready())) {
3034 if (!a2dp_combo) {
3035 check_a2dp_restore_l(adev, out, false);
3036 } else {
3037 audio_devices_t dev = out->devices;
3038 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3039 select_devices(adev, out->usecase);
3040 out->devices = dev;
3041 }
3042 } else {
3043 select_devices(adev, out->usecase);
3044 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003045
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003046 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3047 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003048
3049 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3050 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3051 ALOGE("%s: pcm stream not ready", __func__);
3052 goto error_open;
3053 }
3054 ret = pcm_start(out->pcm);
3055 if (ret < 0) {
3056 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3057 goto error_open;
3058 }
3059 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003060 unsigned int flags = PCM_OUT;
3061 unsigned int pcm_open_retry_count = 0;
3062 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3063 flags |= PCM_MMAP | PCM_NOIRQ;
3064 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003065 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003066 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003067 } else
3068 flags |= PCM_MONOTONIC;
3069
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003070 if ((adev->vr_audio_mode_enabled) &&
3071 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3072 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3073 "PCM_Dev %d Topology", out->pcm_device_id);
3074 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3075 if (!ctl) {
3076 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3077 __func__, mixer_ctl_name);
3078 } else {
3079 //if success use ULLPP
3080 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3081 __func__, mixer_ctl_name, out->pcm_device_id);
3082 //There is a still a possibility that some sessions
3083 // that request for FAST|RAW when 3D audio is active
3084 //can go through ULLPP. Ideally we expects apps to
3085 //listen to audio focus and stop concurrent playback
3086 //Also, we will look for mode flag (voice_in_communication)
3087 //before enabling the realtime flag.
3088 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3089 }
3090 }
3091
Surendar Karka91fa3682018-07-02 18:12:12 +05303092 if (out->realtime)
3093 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3094 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3095
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003096 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003097 ATRACE_BEGIN("pcm_open");
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003098 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3099 flags, &out->config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003100 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303101 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303102 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3103 out->card_status = CARD_STATUS_OFFLINE;
3104 adev->card_status = CARD_STATUS_OFFLINE;
3105 ret = -EIO;
3106 goto error_open;
3107 }
3108
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003109 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3110 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3111 if (out->pcm != NULL) {
3112 pcm_close(out->pcm);
3113 out->pcm = NULL;
3114 }
3115 if (pcm_open_retry_count-- == 0) {
3116 ret = -EIO;
3117 goto error_open;
3118 }
3119 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3120 continue;
3121 }
3122 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003123 }
Surendar Karka91fa3682018-07-02 18:12:12 +05303124 if (!out->realtime)
3125 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303126 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003127
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003128 ALOGV("%s: pcm_prepare", __func__);
3129 if (pcm_is_ready(out->pcm)) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003130 ATRACE_BEGIN("pcm_prepare");
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003131 ret = pcm_prepare(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003132 ATRACE_END();
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003133 if (ret < 0) {
3134 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3135 pcm_close(out->pcm);
3136 out->pcm = NULL;
3137 goto error_open;
3138 }
3139 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08003140 // apply volume for voip playback after path is set up
3141 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3142 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003143 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003144 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303145 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003146 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3147 adev->dsp_bit_width_enforce_mode,
3148 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003150 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003151 out->compr = compress_open(adev->snd_card,
3152 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003153 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003154 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303155 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303156 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3157 adev->card_status = CARD_STATUS_OFFLINE;
3158 out->card_status = CARD_STATUS_OFFLINE;
3159 ret = -EIO;
3160 goto error_open;
3161 }
3162
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003163 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003164 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003165 compress_close(out->compr);
3166 out->compr = NULL;
3167 ret = -EIO;
3168 goto error_open;
3169 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303170 /* compress_open sends params of the track, so reset the flag here */
3171 out->is_compr_metadata_avail = false;
3172
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003173 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003174 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003175
Fred Oh3f43e742015-03-04 18:42:34 -08003176 /* Since small bufs uses blocking writes, a write will be blocked
3177 for the default max poll time (20s) in the event of an SSR.
3178 Reduce the poll time to observe and deal with SSR faster.
3179 */
Ashish Jain5106d362016-05-11 19:23:33 +05303180 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003181 compress_set_max_poll_wait(out->compr, 1000);
3182 }
3183
Manish Dewangan69426c82017-01-30 17:35:36 +05303184 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303185 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303186
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003187 audio_extn_dts_create_state_notifier_node(out->usecase);
3188 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3189 popcount(out->channel_mask),
3190 out->playback_started);
3191
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003192#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303193 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003194 audio_extn_dolby_send_ddp_endp_params(adev);
3195#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303196 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3197 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003198 if (adev->visualizer_start_output != NULL)
3199 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3200 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303201 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003202 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003203 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003205
3206 if (ret == 0) {
3207 register_out_stream(out);
3208 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003209 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3210 ALOGE("%s: pcm stream not ready", __func__);
3211 goto error_open;
3212 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003213 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003214 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003215 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003216 if (ret < 0)
3217 goto error_open;
3218 }
3219 }
3220
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303221 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003222 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003223
Manish Dewangan21a850a2017-08-14 12:03:55 +05303224 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003225 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003226 if (ret < 0)
3227 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3228 }
3229
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003230 // consider a scenario where on pause lower layers are tear down.
3231 // so on resume, swap mixer control need to be sent only when
3232 // backend is active, hence rather than sending from enable device
3233 // sending it from start of streamtream
3234
3235 platform_set_swap_channels(adev, true);
3236
Haynes Mathew George380745d2017-10-04 15:27:45 -07003237 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003238 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003239error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303240 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003241 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003242error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303243 /*
3244 * sleep 50ms to allow sufficient time for kernel
3245 * drivers to recover incases like SSR.
3246 */
3247 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003248 ATRACE_END();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003249 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250}
3251
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252static int check_input_parameters(uint32_t sample_rate,
3253 audio_format_t format,
3254 int channel_count)
3255{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003256 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303258 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3259 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3260 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003261 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003262 !audio_extn_compr_cap_format_supported(format) &&
3263 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003264 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003265
3266 switch (channel_count) {
3267 case 1:
3268 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303269 case 3:
3270 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003271 case 6:
Ralf Herzaec80262018-07-03 07:08:49 +02003272 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003273 break;
3274 default:
3275 ret = -EINVAL;
3276 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003277
3278 switch (sample_rate) {
3279 case 8000:
3280 case 11025:
3281 case 12000:
3282 case 16000:
3283 case 22050:
3284 case 24000:
3285 case 32000:
3286 case 44100:
3287 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003288 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303289 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003290 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303291 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292 break;
3293 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003294 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295 }
3296
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003297 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298}
3299
3300static size_t get_input_buffer_size(uint32_t sample_rate,
3301 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003302 int channel_count,
3303 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304{
3305 size_t size = 0;
3306
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003307 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3308 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003310 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003311 if (is_low_latency)
3312 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303313
3314 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003315
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003316 /* make sure the size is multiple of 32 bytes
3317 * At 48 kHz mono 16-bit PCM:
3318 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3319 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
3320 */
3321 size += 0x1f;
3322 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003323
3324 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325}
3326
Ashish Jain058165c2016-09-28 23:18:48 +05303327static size_t get_output_period_size(uint32_t sample_rate,
3328 audio_format_t format,
3329 int channel_count,
3330 int duration /*in millisecs*/)
3331{
3332 size_t size = 0;
3333 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3334
3335 if ((duration == 0) || (sample_rate == 0) ||
3336 (bytes_per_sample == 0) || (channel_count == 0)) {
3337 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3338 bytes_per_sample, channel_count);
3339 return -EINVAL;
3340 }
3341
3342 size = (sample_rate *
3343 duration *
3344 bytes_per_sample *
3345 channel_count) / 1000;
3346 /*
3347 * To have same PCM samples for all channels, the buffer size requires to
3348 * be multiple of (number of channels * bytes per sample)
3349 * For writes to succeed, the buffer must be written at address which is multiple of 32
3350 */
3351 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3352
3353 return (size/(channel_count * bytes_per_sample));
3354}
3355
Zhou Song48453a02018-01-10 17:50:59 +08003356static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303357{
3358 uint64_t actual_frames_rendered = 0;
3359 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3360
3361 /* This adjustment accounts for buffering after app processor.
3362 * It is based on estimated DSP latency per use case, rather than exact.
3363 */
3364 int64_t platform_latency = platform_render_latency(out->usecase) *
3365 out->sample_rate / 1000000LL;
3366
Zhou Song48453a02018-01-10 17:50:59 +08003367 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303368 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3369 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3370 * hence only estimate.
3371 */
3372 int64_t signed_frames = out->written - kernel_buffer_size;
3373
3374 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3375
Zhou Song48453a02018-01-10 17:50:59 +08003376 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303377 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003378 if (timestamp != NULL )
3379 *timestamp = out->writeAt;
3380 } else if (timestamp != NULL) {
3381 clock_gettime(CLOCK_MONOTONIC, timestamp);
3382 }
3383 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303384
3385 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3386 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3387 (long long int)out->written, (int)kernel_buffer_size,
3388 audio_bytes_per_sample(out->compr_config.codec->format),
3389 popcount(out->channel_mask));
3390
3391 return actual_frames_rendered;
3392}
3393
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3395{
3396 struct stream_out *out = (struct stream_out *)stream;
3397
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003398 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399}
3400
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003401static int out_set_sample_rate(struct audio_stream *stream __unused,
3402 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403{
3404 return -ENOSYS;
3405}
3406
3407static size_t out_get_buffer_size(const struct audio_stream *stream)
3408{
3409 struct stream_out *out = (struct stream_out *)stream;
3410
Varun Balaraje49253e2017-07-06 19:48:56 +05303411 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303412 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303413 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303414 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3415 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3416 else
3417 return out->compr_config.fragment_size;
3418 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003419 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003420 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3421 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 +05303422 else if (is_offload_usecase(out->usecase) &&
3423 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303424 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003425
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003426 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003427 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428}
3429
3430static uint32_t out_get_channels(const struct audio_stream *stream)
3431{
3432 struct stream_out *out = (struct stream_out *)stream;
3433
3434 return out->channel_mask;
3435}
3436
3437static audio_format_t out_get_format(const struct audio_stream *stream)
3438{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003439 struct stream_out *out = (struct stream_out *)stream;
3440
3441 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442}
3443
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003444static int out_set_format(struct audio_stream *stream __unused,
3445 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003446{
3447 return -ENOSYS;
3448}
3449
3450static int out_standby(struct audio_stream *stream)
3451{
3452 struct stream_out *out = (struct stream_out *)stream;
3453 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003454 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003455
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303456 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3457 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003458
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003459 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003461 if (adev->adm_deregister_stream)
3462 adev->adm_deregister_stream(adev->adm_data, out->handle);
3463
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003464 if (is_offload_usecase(out->usecase))
3465 stop_compressed_output_l(out);
3466
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003467 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003469 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3470 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303471 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003472 pthread_mutex_unlock(&adev->lock);
3473 pthread_mutex_unlock(&out->lock);
3474 ALOGD("VOIP output entered standby");
3475 return 0;
3476 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003477 if (out->pcm) {
3478 pcm_close(out->pcm);
3479 out->pcm = NULL;
3480 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003481 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3482 do_stop = out->playback_started;
3483 out->playback_started = false;
3484 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003485 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003486 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303487 out->send_next_track_params = false;
3488 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003489 out->gapless_mdata.encoder_delay = 0;
3490 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003491 if (out->compr != NULL) {
3492 compress_close(out->compr);
3493 out->compr = NULL;
3494 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003495 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003496 if (do_stop) {
3497 stop_output_stream(out);
3498 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003499 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003500 }
3501 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303502 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503 return 0;
3504}
3505
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303506static int out_on_error(struct audio_stream *stream)
3507{
3508 struct stream_out *out = (struct stream_out *)stream;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303509
3510 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003511 // always send CMD_ERROR for offload streams, this
3512 // is needed e.g. when SSR happens within compress_open
3513 // since the stream is active, offload_callback_thread is also active.
3514 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3515 stop_compressed_output_l(out);
3516 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303517 }
3518 pthread_mutex_unlock(&out->lock);
3519
Aniket Kumar Lata28abfc12017-12-28 10:53:07 -08003520 return out_standby(&out->stream.common);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303521}
3522
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303523/*
3524 *standby implementation without locks, assumes that the callee already
3525 *has taken adev and out lock.
3526 */
3527int out_standby_l(struct audio_stream *stream)
3528{
3529 struct stream_out *out = (struct stream_out *)stream;
3530 struct audio_device *adev = out->dev;
3531
3532 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3533 stream, out->usecase, use_case_table[out->usecase]);
3534
3535 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003536 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303537 if (adev->adm_deregister_stream)
3538 adev->adm_deregister_stream(adev->adm_data, out->handle);
3539
3540 if (is_offload_usecase(out->usecase))
3541 stop_compressed_output_l(out);
3542
3543 out->standby = true;
3544 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3545 voice_extn_compress_voip_close_output_stream(stream);
3546 out->started = 0;
3547 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003548 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303549 return 0;
3550 } else if (!is_offload_usecase(out->usecase)) {
3551 if (out->pcm) {
3552 pcm_close(out->pcm);
3553 out->pcm = NULL;
3554 }
3555 } else {
3556 ALOGD("copl(%p):standby", out);
3557 out->send_next_track_params = false;
3558 out->is_compr_metadata_avail = false;
3559 out->gapless_mdata.encoder_delay = 0;
3560 out->gapless_mdata.encoder_padding = 0;
3561 if (out->compr != NULL) {
3562 compress_close(out->compr);
3563 out->compr = NULL;
3564 }
3565 }
3566 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003567 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303568 }
3569 ALOGD("%s: exit", __func__);
3570 return 0;
3571}
3572
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003573static int out_dump(const struct audio_stream *stream __unused,
3574 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003575{
3576 return 0;
3577}
3578
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003579static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3580{
3581 int ret = 0;
3582 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003583
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003584 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003585 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003586 return -EINVAL;
3587 }
3588
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303589 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003590
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003591 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3592 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303593 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003594 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003595 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3596 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303597 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003598 }
3599
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003600 ALOGV("%s new encoder delay %u and padding %u", __func__,
3601 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3602
3603 return 0;
3604}
3605
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003606static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3607{
3608 return out == adev->primary_output || out == adev->voice_tx_output;
3609}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003610
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303611// note: this call is safe only if the stream_cb is
3612// removed first in close_output_stream (as is done now).
3613static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3614{
3615 if (!stream || !parms)
3616 return;
3617
3618 struct stream_out *out = (struct stream_out *)stream;
3619 struct audio_device *adev = out->dev;
3620
3621 card_status_t status;
3622 int card;
3623 if (parse_snd_card_status(parms, &card, &status) < 0)
3624 return;
3625
3626 pthread_mutex_lock(&adev->lock);
3627 bool valid_cb = (card == adev->snd_card);
3628 pthread_mutex_unlock(&adev->lock);
3629
3630 if (!valid_cb)
3631 return;
3632
3633 lock_output_stream(out);
3634 if (out->card_status != status)
3635 out->card_status = status;
3636 pthread_mutex_unlock(&out->lock);
3637
3638 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3639 use_case_table[out->usecase],
3640 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3641
3642 if (status == CARD_STATUS_OFFLINE)
3643 out_on_error(stream);
3644
3645 return;
3646}
3647
Kevin Rocardfce19002017-08-07 19:21:36 -07003648static int get_alive_usb_card(struct str_parms* parms) {
3649 int card;
3650 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
3651 !audio_extn_usb_alive(card)) {
3652 return card;
3653 }
3654 return -ENODEV;
3655}
3656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3658{
3659 struct stream_out *out = (struct stream_out *)stream;
3660 struct audio_device *adev = out->dev;
3661 struct str_parms *parms;
3662 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003663 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303664 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003665
sangwoobc677242013-08-08 16:53:43 +09003666 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003667 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303669 if (!parms)
3670 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003671 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3672 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003674 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003675 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003676
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003677 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003678 * When HDMI cable is unplugged the music playback is paused and
3679 * the policy manager sends routing=0. But the audioflinger continues
3680 * to write data until standby time (3sec). As the HDMI core is
3681 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003682 * Avoid this by routing audio to speaker until standby.
3683 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003684 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3685 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303686 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003687 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3688 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003689 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303690 /*
3691 * When A2DP is disconnected the
3692 * music playback is paused and the policy manager sends routing=0
3693 * But the audioflingercontinues to write data until standby time
3694 * (3sec). As BT is turned off, the write gets blocked.
3695 * Avoid this by routing audio to speaker until standby.
3696 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003697 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07003698 (val == AUDIO_DEVICE_NONE) &&
3699 !audio_extn_a2dp_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303700 val = AUDIO_DEVICE_OUT_SPEAKER;
3701 }
Sharad Sangle67d9e7c2018-04-05 23:28:32 +05303702 /*
3703 * When USB headset is disconnected the music platback paused
3704 * and the policy manager send routing=0. But if the USB is connected
3705 * back before the standby time, AFE is not closed and opened
3706 * when USB is connected back. So routing to speker will guarantee
3707 * AFE reconfiguration and AFE will be opend once USB is connected again
3708 */
3709 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
3710 (val == AUDIO_DEVICE_NONE) &&
3711 !audio_extn_usb_connected(parms)) {
3712 val = AUDIO_DEVICE_OUT_SPEAKER;
3713 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303714 /* To avoid a2dp to sco overlapping / BT device improper state
3715 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303716 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303717 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3718 if (!audio_extn_a2dp_is_ready()) {
3719 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3720 //combo usecase just by pass a2dp
3721 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303722 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303723 } else {
3724 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3725 /* update device to a2dp and don't route as BT returned error
3726 * However it is still possible a2dp routing called because
3727 * of current active device disconnection (like wired headset)
3728 */
3729 out->devices = val;
3730 pthread_mutex_unlock(&out->lock);
3731 pthread_mutex_unlock(&adev->lock);
3732 goto error;
3733 }
3734 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303735 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003736
3737 audio_devices_t new_dev = val;
3738
3739 // Workaround: If routing to an non existing usb device, fail gracefully
3740 // The routing request will otherwise block during 10 second
3741 int card;
3742 if (audio_is_usb_out_device(new_dev) &&
3743 (card = get_alive_usb_card(parms)) >= 0) {
3744
3745 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
3746 pthread_mutex_unlock(&adev->lock);
3747 pthread_mutex_unlock(&out->lock);
3748 ret = -ENOSYS;
3749 goto routing_fail;
3750 }
3751
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003752 /*
3753 * select_devices() call below switches all the usecases on the same
3754 * backend to the new device. Refer to check_usecases_codec_backend() in
3755 * the select_devices(). But how do we undo this?
3756 *
3757 * For example, music playback is active on headset (deep-buffer usecase)
3758 * and if we go to ringtones and select a ringtone, low-latency usecase
3759 * will be started on headset+speaker. As we can't enable headset+speaker
3760 * and headset devices at the same time, select_devices() switches the music
3761 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3762 * So when the ringtone playback is completed, how do we undo the same?
3763 *
3764 * We are relying on the out_set_parameters() call on deep-buffer output,
3765 * once the ringtone playback is ended.
3766 * NOTE: We should not check if the current devices are same as new devices.
3767 * Because select_devices() must be called to switch back the music
3768 * playback to headset.
3769 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003770 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003771 audio_devices_t new_dev = val;
3772 bool same_dev = out->devices == new_dev;
3773 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003774
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003775 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08003776 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003777 if (adev->mode == AUDIO_MODE_IN_CALL) {
3778 adev->current_call_output = out;
3779 ret = voice_start_call(adev);
3780 }
3781 } else {
3782 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003783 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003784 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003785 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003786
3787 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003788 if (!same_dev) {
3789 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303790 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3791 adev->perf_lock_opts,
3792 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003793 if (adev->adm_on_routing_change)
3794 adev->adm_on_routing_change(adev->adm_data,
3795 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003796 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303797 if (!bypass_a2dp) {
3798 select_devices(adev, out->usecase);
3799 } else {
3800 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3801 select_devices(adev, out->usecase);
3802 out->devices = new_dev;
3803 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003804
3805 if (!same_dev) {
3806 // on device switch force swap, lower functions will make sure
3807 // to check if swap is allowed or not.
3808 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05303809 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003810 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303811 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3812 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003813 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303814 pthread_mutex_lock(&out->compr_mute_lock);
3815 out->a2dp_compress_mute = false;
3816 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3817 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08003818 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
3819 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303820 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003821 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003822 }
3823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003824 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003825 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003826 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003827 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003828
3829 if (out == adev->primary_output) {
3830 pthread_mutex_lock(&adev->lock);
3831 audio_extn_set_parameters(adev, parms);
3832 pthread_mutex_unlock(&adev->lock);
3833 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003834 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003835 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003836 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003837
3838 audio_extn_dts_create_state_notifier_node(out->usecase);
3839 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3840 popcount(out->channel_mask),
3841 out->playback_started);
3842
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003843 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003844 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003845
Surendar Karkaf51b5842018-04-26 11:28:38 +05303846 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
3847 sizeof(value));
3848 if (err >= 0) {
3849 if (!strncmp("true", value, sizeof("true")) || atoi(value))
3850 audio_extn_send_dual_mono_mixing_coefficients(out);
3851 }
3852
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303853 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3854 if (err >= 0) {
3855 strlcpy(out->profile, value, sizeof(out->profile));
3856 ALOGV("updating stream profile with value '%s'", out->profile);
3857 lock_output_stream(out);
3858 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3859 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07003860 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303861 out->sample_rate, out->bit_width,
3862 out->channel_mask, out->profile,
3863 &out->app_type_cfg);
3864 pthread_mutex_unlock(&out->lock);
3865 }
3866
Alexy Joseph98988832017-01-13 14:56:59 -08003867 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08003868 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
3869 // and vendor.audio.hal.output.suspend.supported is set to true
3870 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08003871 //check suspend parameter only for low latency and if the property
3872 //is enabled
3873 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3874 ALOGI("%s: got suspend_playback %s", __func__, value);
3875 lock_output_stream(out);
3876 if (!strncmp(value, "false", 5)) {
3877 //suspend_playback=false is supposed to set QOS value back to 75%
3878 //the mixer control sent with value Enable will achieve that
3879 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3880 } else if (!strncmp (value, "true", 4)) {
3881 //suspend_playback=true is supposed to remove QOS value
3882 //resetting the mixer control will set the default value
3883 //for the mixer control which is Disable and this removes the QOS vote
3884 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3885 } else {
3886 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3887 " got %s", __func__, value);
3888 ret = -1;
3889 }
3890
3891 if (ret != 0) {
3892 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3893 __func__, out->pm_qos_mixer_path, ret);
3894 }
3895
3896 pthread_mutex_unlock(&out->lock);
3897 }
3898 }
3899 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303901error:
Eric Laurent994a6932013-07-17 11:51:42 -07003902 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903 return ret;
3904}
3905
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003906static bool stream_get_parameter_channels(struct str_parms *query,
3907 struct str_parms *reply,
3908 audio_channel_mask_t *supported_channel_masks) {
3909 int ret = -1;
3910 char value[512];
3911 bool first = true;
3912 size_t i, j;
3913
3914 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3915 ret = 0;
3916 value[0] = '\0';
3917 i = 0;
3918 while (supported_channel_masks[i] != 0) {
3919 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3920 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
3921 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303922 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003923
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303924 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003925 first = false;
3926 break;
3927 }
3928 }
3929 i++;
3930 }
3931 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3932 }
3933 return ret == 0;
3934}
3935
3936static bool stream_get_parameter_formats(struct str_parms *query,
3937 struct str_parms *reply,
3938 audio_format_t *supported_formats) {
3939 int ret = -1;
3940 char value[256];
3941 size_t i, j;
3942 bool first = true;
3943
3944 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
3945 ret = 0;
3946 value[0] = '\0';
3947 i = 0;
3948 while (supported_formats[i] != 0) {
3949 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
3950 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
3951 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303952 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003953 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303954 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003955 first = false;
3956 break;
3957 }
3958 }
3959 i++;
3960 }
3961 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
3962 }
3963 return ret == 0;
3964}
3965
3966static bool stream_get_parameter_rates(struct str_parms *query,
3967 struct str_parms *reply,
3968 uint32_t *supported_sample_rates) {
3969
3970 int i;
3971 char value[256];
3972 int ret = -1;
3973 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
3974 ret = 0;
3975 value[0] = '\0';
3976 i=0;
3977 int cursor = 0;
3978 while (supported_sample_rates[i]) {
3979 int avail = sizeof(value) - cursor;
3980 ret = snprintf(value + cursor, avail, "%s%d",
3981 cursor > 0 ? "|" : "",
3982 supported_sample_rates[i]);
3983 if (ret < 0 || ret >= avail) {
3984 // if cursor is at the last element of the array
3985 // overwrite with \0 is duplicate work as
3986 // snprintf already put a \0 in place.
3987 // else
3988 // we had space to write the '|' at value[cursor]
3989 // (which will be overwritten) or no space to fill
3990 // the first element (=> cursor == 0)
3991 value[cursor] = '\0';
3992 break;
3993 }
3994 cursor += ret;
3995 ++i;
3996 }
3997 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3998 value);
3999 }
4000 return ret >= 0;
4001}
4002
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004003static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4004{
4005 struct stream_out *out = (struct stream_out *)stream;
4006 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004007 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004008 char value[256];
4009 struct str_parms *reply = str_parms_create();
4010 size_t i, j;
4011 int ret;
4012 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004013
4014 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004015 if (reply) {
4016 str_parms_destroy(reply);
4017 }
4018 if (query) {
4019 str_parms_destroy(query);
4020 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004021 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4022 return NULL;
4023 }
4024
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004025 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004026 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4027 if (ret >= 0) {
4028 value[0] = '\0';
4029 i = 0;
4030 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004031 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4032 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004033 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004034 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004035 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004036 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004037 first = false;
4038 break;
4039 }
4040 }
4041 i++;
4042 }
4043 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4044 str = str_parms_to_str(reply);
4045 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004046 voice_extn_out_get_parameters(out, query, reply);
4047 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004048 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004049
Alexy Joseph62142aa2015-11-16 15:10:34 -08004050
4051 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4052 if (ret >= 0) {
4053 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304054 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4055 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004056 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304057 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004058 } else {
4059 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304060 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004061 }
4062 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004063 if (str)
4064 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004065 str = str_parms_to_str(reply);
4066 }
4067
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004068 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4069 if (ret >= 0) {
4070 value[0] = '\0';
4071 i = 0;
4072 first = true;
4073 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004074 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4075 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004076 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004077 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004078 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004079 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004080 first = false;
4081 break;
4082 }
4083 }
4084 i++;
4085 }
4086 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004087 if (str)
4088 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004089 str = str_parms_to_str(reply);
4090 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004091
4092 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4093 if (ret >= 0) {
4094 value[0] = '\0';
4095 i = 0;
4096 first = true;
4097 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004098 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4099 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004100 if (!first) {
4101 strlcat(value, "|", sizeof(value));
4102 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004103 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004104 first = false;
4105 break;
4106 }
4107 }
4108 i++;
4109 }
4110 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4111 if (str)
4112 free(str);
4113 str = str_parms_to_str(reply);
4114 }
4115
Alexy Joseph98988832017-01-13 14:56:59 -08004116 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4117 //only low latency track supports suspend_resume
4118 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004119 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004120 if (str)
4121 free(str);
4122 str = str_parms_to_str(reply);
4123 }
4124
4125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004126 str_parms_destroy(query);
4127 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004128 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004129 return str;
4130}
4131
4132static uint32_t out_get_latency(const struct audio_stream_out *stream)
4133{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004134 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004135 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004136 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137
Alexy Josephaa54c872014-12-03 02:46:47 -08004138 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304139 lock_output_stream(out);
4140 latency = audio_extn_utils_compress_get_dsp_latency(out);
4141 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004142 } else if ((out->realtime) ||
4143 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004144 // since the buffer won't be filled up faster than realtime,
4145 // return a smaller number
4146 if (out->config.rate)
4147 period_ms = (out->af_period_multiplier * out->config.period_size *
4148 1000) / (out->config.rate);
4149 else
4150 period_ms = 0;
4151 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004152 } else {
4153 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004154 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004155 }
4156
yidongh0515e042017-07-06 15:00:34 +08004157 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004158 latency += audio_extn_a2dp_get_encoder_latency();
4159
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304160 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004161 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162}
4163
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304164static float AmpToDb(float amplification)
4165{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304166 float db = DSD_VOLUME_MIN_DB;
4167 if (amplification > 0) {
4168 db = 20 * log10(amplification);
4169 if(db < DSD_VOLUME_MIN_DB)
4170 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304171 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304172 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304173}
4174
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304175static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4176 float right)
4177{
4178 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304179 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304180 char mixer_ctl_name[128];
4181 struct audio_device *adev = out->dev;
4182 struct mixer_ctl *ctl;
4183 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4184 PCM_PLAYBACK);
4185
4186 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4187 "Compress Playback %d Volume", pcm_device_id);
4188 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4189 if (!ctl) {
4190 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4191 __func__, mixer_ctl_name);
4192 return -EINVAL;
4193 }
4194 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4195 __func__, mixer_ctl_name, left, right);
4196 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4197 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4198 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4199
4200 return 0;
4201}
4202
Zhou Song2b8f28f2017-09-11 10:51:38 +08004203static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4204 float right)
4205{
4206 struct stream_out *out = (struct stream_out *)stream;
4207 char mixer_ctl_name[] = "App Type Gain";
4208 struct audio_device *adev = out->dev;
4209 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304210 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004211
4212 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4213 if (!ctl) {
4214 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4215 __func__, mixer_ctl_name);
4216 return -EINVAL;
4217 }
4218
4219 set_values[0] = 0; //0: Rx Session 1:Tx Session
4220 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304221 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4222 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004223
4224 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4225 return 0;
4226}
4227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004228static int out_set_volume(struct audio_stream_out *stream, float left,
4229 float right)
4230{
Eric Laurenta9024de2013-04-04 09:19:12 -07004231 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004232 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304233 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004234
Eric Laurenta9024de2013-04-04 09:19:12 -07004235 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4236 /* only take left channel into account: the API is for stereo anyway */
4237 out->muted = (left == 0.0f);
4238 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004239 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304240 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004241 /*
4242 * Set mute or umute on HDMI passthrough stream.
4243 * Only take left channel into account.
4244 * Mute is 0 and unmute 1
4245 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304246 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304247 } else if (out->format == AUDIO_FORMAT_DSD){
4248 char mixer_ctl_name[128] = "DSD Volume";
4249 struct audio_device *adev = out->dev;
4250 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4251
4252 if (!ctl) {
4253 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4254 __func__, mixer_ctl_name);
4255 return -EINVAL;
4256 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304257 volume[0] = (long)(AmpToDb(left));
4258 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304259 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4260 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004261 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304262 pthread_mutex_lock(&out->compr_mute_lock);
4263 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
4264 if (!out->a2dp_compress_mute)
4265 ret = out_set_compr_volume(stream, left, right);
4266 out->volume_l = left;
4267 out->volume_r = right;
4268 pthread_mutex_unlock(&out->compr_mute_lock);
4269 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004270 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004271 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004272 if (!out->standby)
4273 ret = out_set_voip_volume(stream, left, right);
4274 out->volume_l = left;
4275 out->volume_r = right;
4276 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004277 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004278
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004279 return -ENOSYS;
4280}
4281
Zhou Songc9672822017-08-16 16:01:39 +08004282static void update_frames_written(struct stream_out *out, size_t bytes)
4283{
4284 size_t bpf = 0;
4285
4286 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4287 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4288 bpf = 1;
4289 else if (!is_offload_usecase(out->usecase))
4290 bpf = audio_bytes_per_sample(out->format) *
4291 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004292
4293 pthread_mutex_lock(&out->position_query_lock);
4294 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004295 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004296 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4297 }
4298 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004299}
4300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004301static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4302 size_t bytes)
4303{
4304 struct stream_out *out = (struct stream_out *)stream;
4305 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004306 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304307 int channels = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004308
Haynes Mathew George380745d2017-10-04 15:27:45 -07004309 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004310 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304311
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304312 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004313
Dhananjay Kumarac341582017-02-23 23:42:25 +05304314 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304315 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304316 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4317 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004318 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304319 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304320 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304321 ALOGD(" %s: sound card is not active/SSR state", __func__);
4322 ret= -EIO;
4323 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304324 }
4325 }
4326
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304327 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304328 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304329 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304330 goto exit;
4331 }
4332
Haynes Mathew George16081042017-05-31 17:16:49 -07004333 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4334 ret = -EINVAL;
4335 goto exit;
4336 }
4337
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304338 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4339 !out->is_iec61937_info_available) {
4340
4341 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4342 out->is_iec61937_info_available = true;
4343 } else if (audio_extn_passthru_is_enabled()) {
4344 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304345 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304346
4347 if((out->format == AUDIO_FORMAT_DTS) ||
4348 (out->format == AUDIO_FORMAT_DTS_HD)) {
4349 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4350 buffer, bytes);
4351 if (ret) {
4352 if (ret != -ENOSYS) {
4353 out->is_iec61937_info_available = false;
4354 ALOGD("iec61937 transmission info not yet updated retry");
4355 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304356 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304357 /* if stream has started and after that there is
4358 * stream config change (iec transmission config)
4359 * then trigger select_device to update backend configuration.
4360 */
4361 out->stream_config_changed = true;
4362 pthread_mutex_lock(&adev->lock);
4363 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304364 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4365 ret = -EINVAL;
4366 goto exit;
4367 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304368 pthread_mutex_unlock(&adev->lock);
4369 out->stream_config_changed = false;
4370 out->is_iec61937_info_available = true;
4371 }
4372 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304373
Garmond Leung317cbf12017-09-13 16:20:50 -07004374 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304375 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4376 (out->is_iec61937_info_available == true)) {
4377 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4378 ret = -EINVAL;
4379 goto exit;
4380 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304381 }
4382 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304383
4384 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4385 (audio_extn_a2dp_is_suspended())) {
4386 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4387 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304388 ret = -EIO;
4389 goto exit;
4390 }
4391 }
4392 }
4393
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004394 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004395 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004396 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004397 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4398 ret = voice_extn_compress_voip_start_output_stream(out);
4399 else
4400 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004401 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004402 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004403 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004404 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004405 goto exit;
4406 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304407 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004408 if (last_known_cal_step != -1) {
4409 ALOGD("%s: retry previous failed cal level set", __func__);
4410 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304411 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004412 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304413
4414 if ((out->is_iec61937_info_available == true) &&
4415 (audio_extn_passthru_is_passthrough_stream(out))&&
4416 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4417 ret = -EINVAL;
4418 goto exit;
4419 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05304420 if (out->set_dual_mono)
4421 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004422 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423
Ashish Jain81eb2a82015-05-13 10:52:34 +05304424 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004425 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304426 adev->is_channel_status_set = true;
4427 }
4428
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004429 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004430 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004431 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004432 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004433 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4434 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304435 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4436 ALOGD("copl(%p):send next track params in gapless", out);
4437 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4438 out->send_next_track_params = false;
4439 out->is_compr_metadata_avail = false;
4440 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004441 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304442 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304443 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004444
Ashish Jain83a6cc22016-06-28 14:34:17 +05304445 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304446 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304447 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304448 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004449 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304450 return -EINVAL;
4451 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304452 audio_format_t dst_format = out->hal_op_format;
4453 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304454
4455 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4456 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4457
Ashish Jain83a6cc22016-06-28 14:34:17 +05304458 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304459 dst_format,
4460 buffer,
4461 src_format,
4462 frames);
4463
Ashish Jain83a6cc22016-06-28 14:34:17 +05304464 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304465 bytes_to_write);
4466
4467 /*Convert written bytes in audio flinger format*/
4468 if (ret > 0)
4469 ret = ((ret * format_to_bitwidth_table[out->format]) /
4470 format_to_bitwidth_table[dst_format]);
4471 }
4472 } else
4473 ret = compress_write(out->compr, buffer, bytes);
4474
Zhou Songc9672822017-08-16 16:01:39 +08004475 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4476 update_frames_written(out, bytes);
4477
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304478 if (ret < 0)
4479 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304480 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304481 /*msg to cb thread only if non blocking write is enabled*/
4482 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304483 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004484 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304485 } else if (-ENETRESET == ret) {
4486 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304487 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304488 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304489 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004490 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304491 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004492 }
Ashish Jain5106d362016-05-11 19:23:33 +05304493
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304494 /* Call compr start only when non-zero bytes of data is there to be rendered */
4495 if (!out->playback_started && ret > 0) {
4496 int status = compress_start(out->compr);
4497 if (status < 0) {
4498 ret = status;
4499 ALOGE("%s: compr start failed with err %d", __func__, errno);
4500 goto exit;
4501 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004502 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004503 out->playback_started = 1;
4504 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004505
4506 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4507 popcount(out->channel_mask),
4508 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004509 }
4510 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004511 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004512 return ret;
4513 } else {
4514 if (out->pcm) {
4515 if (out->muted)
4516 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004517
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304518 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004519
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004520 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004521
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004522 if (out->config.rate)
4523 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4524 out->config.rate;
4525
4526 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4527
4528 request_out_focus(out, ns);
4529
4530 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004531 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004532 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304533 out->convert_buffer != NULL) {
4534
4535 memcpy_by_audio_format(out->convert_buffer,
4536 out->hal_op_format,
4537 buffer,
4538 out->hal_ip_format,
4539 out->config.period_size * out->config.channels);
4540
4541 ret = pcm_write(out->pcm, out->convert_buffer,
4542 (out->config.period_size *
4543 out->config.channels *
4544 format_to_bitwidth_table[out->hal_op_format]));
4545 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304546 /*
4547 * To avoid underrun in DSP when the application is not pumping
4548 * data at required rate, check for the no. of bytes and ignore
4549 * pcm_write if it is less than actual buffer size.
4550 * It is a work around to a change in compress VOIP driver.
4551 */
4552 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4553 bytes < (out->config.period_size * out->config.channels *
4554 audio_bytes_per_sample(out->format))) {
4555 size_t voip_buf_size =
4556 out->config.period_size * out->config.channels *
4557 audio_bytes_per_sample(out->format);
4558 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4559 __func__, bytes, voip_buf_size);
4560 usleep(((uint64_t)voip_buf_size - bytes) *
4561 1000000 / audio_stream_out_frame_size(stream) /
4562 out_get_sample_rate(&out->stream.common));
4563 ret = 0;
4564 } else
4565 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304566 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004567
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004568 release_out_focus(out);
4569
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304570 if (ret < 0)
4571 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004572 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304573 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004574 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004575 }
4576
4577exit:
Zhou Songc9672822017-08-16 16:01:39 +08004578 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304579 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304580 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304581 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004582 pthread_mutex_unlock(&out->lock);
4583
4584 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004585 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004586 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304587 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304588 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304589 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304590 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304591 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304592 out->standby = true;
4593 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304594 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304595 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4596 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4597 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004598
4599 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mohd Mujahid Pashaa6e89492018-04-09 17:49:11 +05304600 ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004601 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004602 return ret;
4603 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004604 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004605 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004606 return bytes;
4607}
4608
4609static int out_get_render_position(const struct audio_stream_out *stream,
4610 uint32_t *dsp_frames)
4611{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004612 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004613
4614 if (dsp_frames == NULL)
4615 return -EINVAL;
4616
4617 *dsp_frames = 0;
4618 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004619 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304620
4621 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4622 * this operation and adev_close_output_stream(where out gets reset).
4623 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304624 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004625 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05304626 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004627 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304628 return 0;
4629 }
4630
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004631 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304632 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304633 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004634 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304635 if (ret < 0)
4636 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004637 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304638 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004639 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304640 if (-ENETRESET == ret) {
4641 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304642 out->card_status = CARD_STATUS_OFFLINE;
4643 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304644 } else if(ret < 0) {
4645 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304646 ret = -EINVAL;
4647 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304648 /*
4649 * Handle corner case where compress session is closed during SSR
4650 * and timestamp is queried
4651 */
4652 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304653 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304654 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304655 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004656 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05304657 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304658 pthread_mutex_unlock(&out->lock);
4659 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004660 } else if (audio_is_linear_pcm(out->format)) {
4661 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004662 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08004663 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004664 } else
4665 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004666}
4667
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004668static int out_add_audio_effect(const struct audio_stream *stream __unused,
4669 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004670{
4671 return 0;
4672}
4673
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004674static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4675 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004676{
4677 return 0;
4678}
4679
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004680static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4681 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004682{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304683 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004684}
4685
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004686static int out_get_presentation_position(const struct audio_stream_out *stream,
4687 uint64_t *frames, struct timespec *timestamp)
4688{
4689 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05304690 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07004691 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004692
Ashish Jain5106d362016-05-11 19:23:33 +05304693 /* below piece of code is not guarded against any lock because audioFliner serializes
4694 * this operation and adev_close_output_stream( where out gets reset).
4695 */
4696 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304697 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004698 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05304699 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4700 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4701 return 0;
4702 }
4703
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004704 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004705
Ashish Jain5106d362016-05-11 19:23:33 +05304706 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4707 ret = compress_get_tstamp(out->compr, &dsp_frames,
4708 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004709 // Adjustment accounts for A2dp encoder latency with offload usecases
4710 // Note: Encoder latency is returned in ms.
4711 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4712 unsigned long offset =
4713 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4714 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4715 }
Ashish Jain5106d362016-05-11 19:23:33 +05304716 ALOGVV("%s rendered frames %ld sample_rate %d",
4717 __func__, dsp_frames, out->sample_rate);
4718 *frames = dsp_frames;
4719 if (ret < 0)
4720 ret = -errno;
4721 if (-ENETRESET == ret) {
4722 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304723 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304724 ret = -EINVAL;
4725 } else
4726 ret = 0;
4727 /* this is the best we can do */
4728 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07004729 } else {
4730 if (out->pcm) {
Weiyin Jiang2da27362018-03-16 12:05:03 +08004731 unsigned int avail;
4732 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
4733 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
4734 int64_t signed_frames = out->written - kernel_buffer_size + avail;
4735 // This adjustment accounts for buffering after app processor.
4736 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07004737 signed_frames -=
Weiyin Jiang2da27362018-03-16 12:05:03 +08004738 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07004739
Weiyin Jiang2da27362018-03-16 12:05:03 +08004740 // Adjustment accounts for A2dp encoder latency with non offload usecases
4741 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
4742 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4743 signed_frames -=
4744 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4745 }
4746
4747 // It would be unusual for this value to be negative, but check just in case ...
4748 if (signed_frames >= 0) {
4749 *frames = signed_frames;
4750 ret = 0;
4751 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004752 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304753 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304754 *frames = out->written;
4755 clock_gettime(CLOCK_MONOTONIC, timestamp);
4756 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004757 }
4758 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004759 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004760 return ret;
4761}
4762
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004763static int out_set_callback(struct audio_stream_out *stream,
4764 stream_callback_t callback, void *cookie)
4765{
4766 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004767 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004768
4769 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004770 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004771 out->client_callback = callback;
4772 out->client_cookie = cookie;
4773 if (out->adsp_hdlr_stream_handle) {
4774 ret = audio_extn_adsp_hdlr_stream_set_callback(
4775 out->adsp_hdlr_stream_handle,
4776 callback,
4777 cookie);
4778 if (ret)
4779 ALOGW("%s:adsp hdlr callback registration failed %d",
4780 __func__, ret);
4781 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004782 pthread_mutex_unlock(&out->lock);
4783 return 0;
4784}
4785
4786static int out_pause(struct audio_stream_out* stream)
4787{
4788 struct stream_out *out = (struct stream_out *)stream;
4789 int status = -ENOSYS;
4790 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004791 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004792 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004793 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004794 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304795 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304796 status = compress_pause(out->compr);
4797
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004798 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004799
Mingming Yin21854652016-04-13 11:54:02 -07004800 if (audio_extn_passthru_is_active()) {
4801 ALOGV("offload use case, pause passthru");
4802 audio_extn_passthru_on_pause(out);
4803 }
4804
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304805 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004806 audio_extn_dts_notify_playback_state(out->usecase, 0,
4807 out->sample_rate, popcount(out->channel_mask),
4808 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004809 }
4810 pthread_mutex_unlock(&out->lock);
4811 }
4812 return status;
4813}
4814
4815static int out_resume(struct audio_stream_out* stream)
4816{
4817 struct stream_out *out = (struct stream_out *)stream;
4818 int status = -ENOSYS;
4819 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004820 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004821 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004822 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004823 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004824 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304825 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304826 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004827 }
4828 if (!status) {
4829 out->offload_state = OFFLOAD_STATE_PLAYING;
4830 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304831 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004832 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4833 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004834 }
4835 pthread_mutex_unlock(&out->lock);
4836 }
4837 return status;
4838}
4839
4840static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
4841{
4842 struct stream_out *out = (struct stream_out *)stream;
4843 int status = -ENOSYS;
4844 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004845 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004846 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004847 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
4848 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
4849 else
4850 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
4851 pthread_mutex_unlock(&out->lock);
4852 }
4853 return status;
4854}
4855
4856static int out_flush(struct audio_stream_out* stream)
4857{
4858 struct stream_out *out = (struct stream_out *)stream;
4859 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004860 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004861 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004862 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004863 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
4864 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004865 } else {
4866 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
4867 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08004868 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004869 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004870 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004871 return 0;
4872 }
4873 return -ENOSYS;
4874}
4875
Haynes Mathew George16081042017-05-31 17:16:49 -07004876static int out_stop(const struct audio_stream_out* stream)
4877{
4878 struct stream_out *out = (struct stream_out *)stream;
4879 struct audio_device *adev = out->dev;
4880 int ret = -ENOSYS;
4881
4882 ALOGV("%s", __func__);
4883 pthread_mutex_lock(&adev->lock);
4884 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4885 out->playback_started && out->pcm != NULL) {
4886 pcm_stop(out->pcm);
4887 ret = stop_output_stream(out);
4888 out->playback_started = false;
4889 }
4890 pthread_mutex_unlock(&adev->lock);
4891 return ret;
4892}
4893
4894static int out_start(const struct audio_stream_out* stream)
4895{
4896 struct stream_out *out = (struct stream_out *)stream;
4897 struct audio_device *adev = out->dev;
4898 int ret = -ENOSYS;
4899
4900 ALOGV("%s", __func__);
4901 pthread_mutex_lock(&adev->lock);
4902 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4903 !out->playback_started && out->pcm != NULL) {
4904 ret = start_output_stream(out);
4905 if (ret == 0) {
4906 out->playback_started = true;
4907 }
4908 }
4909 pthread_mutex_unlock(&adev->lock);
4910 return ret;
4911}
4912
4913/*
4914 * Modify config->period_count based on min_size_frames
4915 */
4916static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
4917{
4918 int periodCountRequested = (min_size_frames + config->period_size - 1)
4919 / config->period_size;
4920 int periodCount = MMAP_PERIOD_COUNT_MIN;
4921
4922 ALOGV("%s original config.period_size = %d config.period_count = %d",
4923 __func__, config->period_size, config->period_count);
4924
4925 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
4926 periodCount *= 2;
4927 }
4928 config->period_count = periodCount;
4929
4930 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
4931}
4932
4933static int out_create_mmap_buffer(const struct audio_stream_out *stream,
4934 int32_t min_size_frames,
4935 struct audio_mmap_buffer_info *info)
4936{
4937 struct stream_out *out = (struct stream_out *)stream;
4938 struct audio_device *adev = out->dev;
4939 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07004940 unsigned int offset1 = 0;
4941 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07004942 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004943 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07004944
4945 ALOGV("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05304946 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07004947 pthread_mutex_lock(&adev->lock);
4948
Sharad Sanglec6f32552018-05-04 16:15:38 +05304949 if (CARD_STATUS_OFFLINE == out->card_status ||
4950 CARD_STATUS_OFFLINE == adev->card_status) {
4951 ALOGW("out->card_status or adev->card_status offline, try again");
4952 ret = -EIO;
4953 goto exit;
4954 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004955 if (info == NULL || min_size_frames == 0) {
4956 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
4957 ret = -EINVAL;
4958 goto exit;
4959 }
4960 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
4961 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
4962 ret = -ENOSYS;
4963 goto exit;
4964 }
4965 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4966 if (out->pcm_device_id < 0) {
4967 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4968 __func__, out->pcm_device_id, out->usecase);
4969 ret = -EINVAL;
4970 goto exit;
4971 }
4972
4973 adjust_mmap_period_count(&out->config, min_size_frames);
4974
4975 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4976 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
4977 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
4978 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304979 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304980 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
4981 out->card_status = CARD_STATUS_OFFLINE;
4982 adev->card_status = CARD_STATUS_OFFLINE;
4983 ret = -EIO;
4984 goto exit;
4985 }
4986
Haynes Mathew George16081042017-05-31 17:16:49 -07004987 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4988 step = "open";
4989 ret = -ENODEV;
4990 goto exit;
4991 }
4992 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
4993 if (ret < 0) {
4994 step = "begin";
4995 goto exit;
4996 }
4997 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
4998 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004999 ret = platform_get_mmap_data_fd(adev->platform,
5000 out->pcm_device_id, 0 /*playback*/,
5001 &info->shared_memory_fd,
5002 &mmap_size);
5003 if (ret < 0) {
5004 step = "get_mmap_fd";
5005 goto exit;
5006 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005007 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005008 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005009
5010 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5011 if (ret < 0) {
5012 step = "commit";
5013 goto exit;
5014 }
5015
5016 out->standby = false;
5017 ret = 0;
5018
5019 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5020 __func__, info->shared_memory_address, info->buffer_size_frames);
5021
5022exit:
5023 if (ret != 0) {
5024 if (out->pcm == NULL) {
5025 ALOGE("%s: %s - %d", __func__, step, ret);
5026 } else {
5027 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5028 pcm_close(out->pcm);
5029 out->pcm = NULL;
5030 }
5031 }
5032 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305033 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005034 return ret;
5035}
5036
5037static int out_get_mmap_position(const struct audio_stream_out *stream,
5038 struct audio_mmap_position *position)
5039{
5040 struct stream_out *out = (struct stream_out *)stream;
5041 ALOGVV("%s", __func__);
5042 if (position == NULL) {
5043 return -EINVAL;
5044 }
5045 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005046 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005047 return -ENOSYS;
5048 }
5049 if (out->pcm == NULL) {
5050 return -ENOSYS;
5051 }
5052
5053 struct timespec ts = { 0, 0 };
5054 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5055 if (ret < 0) {
5056 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5057 return ret;
5058 }
5059 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
5060 return 0;
5061}
5062
5063
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005064/** audio_stream_in implementation **/
5065static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5066{
5067 struct stream_in *in = (struct stream_in *)stream;
5068
5069 return in->config.rate;
5070}
5071
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005072static int in_set_sample_rate(struct audio_stream *stream __unused,
5073 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005074{
5075 return -ENOSYS;
5076}
5077
5078static size_t in_get_buffer_size(const struct audio_stream *stream)
5079{
5080 struct stream_in *in = (struct stream_in *)stream;
5081
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005082 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5083 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005084 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5085 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 -07005086 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5087 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305088 else if(audio_extn_cin_attached_usecase(in->usecase))
5089 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005090
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005091 return in->config.period_size * in->af_period_multiplier *
5092 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005093}
5094
5095static uint32_t in_get_channels(const struct audio_stream *stream)
5096{
5097 struct stream_in *in = (struct stream_in *)stream;
5098
5099 return in->channel_mask;
5100}
5101
5102static audio_format_t in_get_format(const struct audio_stream *stream)
5103{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005104 struct stream_in *in = (struct stream_in *)stream;
5105
5106 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005107}
5108
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005109static int in_set_format(struct audio_stream *stream __unused,
5110 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005111{
5112 return -ENOSYS;
5113}
5114
5115static int in_standby(struct audio_stream *stream)
5116{
5117 struct stream_in *in = (struct stream_in *)stream;
5118 struct audio_device *adev = in->dev;
5119 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305120 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5121 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005122 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305123
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005124 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005125 if (!in->standby && in->is_st_session) {
5126 ALOGD("%s: sound trigger pcm stop lab", __func__);
5127 audio_extn_sound_trigger_stop_lab(in);
5128 in->standby = 1;
5129 }
5130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005131 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005132 if (adev->adm_deregister_stream)
5133 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5134
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005135 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005136 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005137 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005138 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005139 voice_extn_compress_voip_close_input_stream(stream);
5140 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005141 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5142 do_stop = in->capture_started;
5143 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005144 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305145 if (audio_extn_cin_attached_usecase(in->usecase))
5146 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005147 }
5148
5149 if (do_stop) {
Zhou Songa8895042016-07-05 17:54:22 +08005150 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005151 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005152 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005153 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005154 in->pcm = NULL;
5155 }
5156 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005157 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08005158 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005159 }
5160 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005161 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005162 return status;
5163}
5164
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005165static int in_dump(const struct audio_stream *stream __unused,
5166 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005167{
5168 return 0;
5169}
5170
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305171static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5172{
5173 if (!stream || !parms)
5174 return;
5175
5176 struct stream_in *in = (struct stream_in *)stream;
5177 struct audio_device *adev = in->dev;
5178
5179 card_status_t status;
5180 int card;
5181 if (parse_snd_card_status(parms, &card, &status) < 0)
5182 return;
5183
5184 pthread_mutex_lock(&adev->lock);
5185 bool valid_cb = (card == adev->snd_card);
5186 pthread_mutex_unlock(&adev->lock);
5187
5188 if (!valid_cb)
5189 return;
5190
5191 lock_input_stream(in);
5192 if (in->card_status != status)
5193 in->card_status = status;
5194 pthread_mutex_unlock(&in->lock);
5195
5196 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5197 use_case_table[in->usecase],
5198 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5199
5200 // a better solution would be to report error back to AF and let
5201 // it put the stream to standby
5202 if (status == CARD_STATUS_OFFLINE)
5203 in_standby(&in->stream.common);
5204
5205 return;
5206}
5207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005208static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5209{
5210 struct stream_in *in = (struct stream_in *)stream;
5211 struct audio_device *adev = in->dev;
5212 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005213 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005214 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005215
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305216 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005217 parms = str_parms_create_str(kvpairs);
5218
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305219 if (!parms)
5220 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005221 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005222 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005223
5224 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5225 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005226 val = atoi(value);
5227 /* no audio source uses val == 0 */
5228 if ((in->source != val) && (val != 0)) {
5229 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005230 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5231 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5232 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005233 (in->config.rate == 8000 || in->config.rate == 16000 ||
5234 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005235 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005236 err = voice_extn_compress_voip_open_input_stream(in);
5237 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005238 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005239 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005240 }
5241 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005242 }
5243 }
5244
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005245 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5246 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005247 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005248 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5249
5250 // Workaround: If routing to an non existing usb device, fail gracefully
5251 // The routing request will otherwise block during 10 second
5252 int card;
5253 if (audio_is_usb_in_device(val) &&
5254 (card = get_alive_usb_card(parms)) >= 0) {
5255
5256 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5257 ret = -ENOSYS;
5258 } else {
5259
5260 in->device = val;
5261 /* If recording is in progress, change the tx device to new device */
5262 if (!in->standby && !in->is_st_session) {
5263 ALOGV("update input routing change");
5264 // inform adm before actual routing to prevent glitches.
5265 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005266 adev->adm_on_routing_change(adev->adm_data,
5267 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005268 ret = select_devices(adev, in->usecase);
5269 }
5270 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005271 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005272 }
5273 }
5274
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305275 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5276 if (err >= 0) {
5277 strlcpy(in->profile, value, sizeof(in->profile));
5278 ALOGV("updating stream profile with value '%s'", in->profile);
5279 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5280 &adev->streams_input_cfg_list,
5281 in->device, in->flags, in->format,
5282 in->sample_rate, in->bit_width,
5283 in->profile, &in->app_type_cfg);
5284 }
5285
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005286 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005287 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005288
5289 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305290error:
Eric Laurent994a6932013-07-17 11:51:42 -07005291 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005292 return ret;
5293}
5294
5295static char* in_get_parameters(const struct audio_stream *stream,
5296 const char *keys)
5297{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005298 struct stream_in *in = (struct stream_in *)stream;
5299 struct str_parms *query = str_parms_create_str(keys);
5300 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005301 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005302
5303 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005304 if (reply) {
5305 str_parms_destroy(reply);
5306 }
5307 if (query) {
5308 str_parms_destroy(query);
5309 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005310 ALOGE("in_get_parameters: failed to create query or reply");
5311 return NULL;
5312 }
5313
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005314 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005315
5316 voice_extn_in_get_parameters(in, query, reply);
5317
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005318 stream_get_parameter_channels(query, reply,
5319 &in->supported_channel_masks[0]);
5320 stream_get_parameter_formats(query, reply,
5321 &in->supported_formats[0]);
5322 stream_get_parameter_rates(query, reply,
5323 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005324 str = str_parms_to_str(reply);
5325 str_parms_destroy(query);
5326 str_parms_destroy(reply);
5327
5328 ALOGV("%s: exit: returns - %s", __func__, str);
5329 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005330}
5331
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005332static int in_set_gain(struct audio_stream_in *stream __unused,
5333 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005334{
5335 return 0;
5336}
5337
5338static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5339 size_t bytes)
5340{
5341 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305342
5343 if (in == NULL) {
5344 ALOGE("%s: stream_in ptr is NULL", __func__);
5345 return -EINVAL;
5346 }
5347
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005348 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305349 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305350 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005351
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005352 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305353
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005354 if (in->is_st_session) {
5355 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5356 /* Read from sound trigger HAL */
5357 audio_extn_sound_trigger_read(in, buffer, bytes);
5358 pthread_mutex_unlock(&in->lock);
5359 return bytes;
5360 }
5361
Haynes Mathew George16081042017-05-31 17:16:49 -07005362 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5363 ret = -ENOSYS;
5364 goto exit;
5365 }
5366
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005367 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005368 pthread_mutex_lock(&adev->lock);
5369 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5370 ret = voice_extn_compress_voip_start_input_stream(in);
5371 else
5372 ret = start_input_stream(in);
5373 pthread_mutex_unlock(&adev->lock);
5374 if (ret != 0) {
5375 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005376 }
5377 in->standby = 0;
5378 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005379
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005380 // what's the duration requested by the client?
5381 long ns = 0;
5382
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305383 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005384 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5385 in->config.rate;
5386
5387 request_in_focus(in, ns);
5388 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005389
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305390 if (audio_extn_cin_attached_usecase(in->usecase)) {
5391 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5392 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305393 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005394 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305395 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005396 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005397 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005398 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005399 } else if (audio_extn_ffv_get_stream() == in) {
5400 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305401 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005402 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305403 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5404 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5405 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5406 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305407 ret = -EINVAL;
5408 goto exit;
5409 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305410 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305411 ret = -errno;
5412 }
5413 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305414 /* bytes read is always set to bytes for non compress usecases */
5415 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005416 }
5417
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005418 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005420 /*
5421 * Instead of writing zeroes here, we could trust the hardware
5422 * to always provide zeroes when muted.
5423 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305424 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5425 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005426 memset(buffer, 0, bytes);
5427
5428exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005429 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305430 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005431 pthread_mutex_unlock(&in->lock);
5432
5433 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305434 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305435 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305436 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305437 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305438 in->standby = true;
5439 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305440 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5441 bytes_read = bytes;
5442 memset(buffer, 0, bytes);
5443 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005444 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005445 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305446 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305447 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005448 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305449 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005450}
5451
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005452static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005453{
5454 return 0;
5455}
5456
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005457static int add_remove_audio_effect(const struct audio_stream *stream,
5458 effect_handle_t effect,
5459 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005460{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005461 struct stream_in *in = (struct stream_in *)stream;
5462 int status = 0;
5463 effect_descriptor_t desc;
5464
5465 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005466 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5467
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005468 if (status != 0)
5469 return status;
5470
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005471 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005472 pthread_mutex_lock(&in->dev->lock);
kunleiz67646da2018-04-09 11:12:32 +08005473 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5474 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005475 in->enable_aec != enable &&
5476 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5477 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005478 if (!in->standby) {
5479 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5480 select_devices(in->dev, in->usecase);
5481 }
5482
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005483 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005484 if (in->enable_ns != enable &&
5485 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5486 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005487 if (!in->standby) {
kunleiz67646da2018-04-09 11:12:32 +08005488 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5489 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005490 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5491 select_devices(in->dev, in->usecase);
5492 } else
5493 select_devices(in->dev, in->usecase);
5494 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005495 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005496 pthread_mutex_unlock(&in->dev->lock);
5497 pthread_mutex_unlock(&in->lock);
5498
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005499 return 0;
5500}
5501
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005502static int in_add_audio_effect(const struct audio_stream *stream,
5503 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005504{
Eric Laurent994a6932013-07-17 11:51:42 -07005505 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005506 return add_remove_audio_effect(stream, effect, true);
5507}
5508
5509static int in_remove_audio_effect(const struct audio_stream *stream,
5510 effect_handle_t effect)
5511{
Eric Laurent994a6932013-07-17 11:51:42 -07005512 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005513 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005514}
5515
Haynes Mathew George16081042017-05-31 17:16:49 -07005516static int in_stop(const struct audio_stream_in* stream)
5517{
5518 struct stream_in *in = (struct stream_in *)stream;
5519 struct audio_device *adev = in->dev;
5520
5521 int ret = -ENOSYS;
5522 ALOGV("%s", __func__);
5523 pthread_mutex_lock(&adev->lock);
5524 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5525 in->capture_started && in->pcm != NULL) {
5526 pcm_stop(in->pcm);
5527 ret = stop_input_stream(in);
5528 in->capture_started = false;
5529 }
5530 pthread_mutex_unlock(&adev->lock);
5531 return ret;
5532}
5533
5534static int in_start(const struct audio_stream_in* stream)
5535{
5536 struct stream_in *in = (struct stream_in *)stream;
5537 struct audio_device *adev = in->dev;
5538 int ret = -ENOSYS;
5539
5540 ALOGV("%s in %p", __func__, in);
5541 pthread_mutex_lock(&adev->lock);
5542 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5543 !in->capture_started && in->pcm != NULL) {
5544 if (!in->capture_started) {
5545 ret = start_input_stream(in);
5546 if (ret == 0) {
5547 in->capture_started = true;
5548 }
5549 }
5550 }
5551 pthread_mutex_unlock(&adev->lock);
5552 return ret;
5553}
5554
5555static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5556 int32_t min_size_frames,
5557 struct audio_mmap_buffer_info *info)
5558{
5559 struct stream_in *in = (struct stream_in *)stream;
5560 struct audio_device *adev = in->dev;
5561 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005562 unsigned int offset1 = 0;
5563 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005564 const char *step = "";
5565
5566 pthread_mutex_lock(&adev->lock);
5567 ALOGV("%s in %p", __func__, in);
5568
Sharad Sanglec6f32552018-05-04 16:15:38 +05305569 if (CARD_STATUS_OFFLINE == in->card_status||
5570 CARD_STATUS_OFFLINE == adev->card_status) {
5571 ALOGW("in->card_status or adev->card_status offline, try again");
5572 ret = -EIO;
5573 goto exit;
5574 }
5575
Haynes Mathew George16081042017-05-31 17:16:49 -07005576 if (info == NULL || min_size_frames == 0) {
5577 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5578 ret = -EINVAL;
5579 goto exit;
5580 }
5581 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5582 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5583 ALOGV("%s in %p", __func__, in);
5584 ret = -ENOSYS;
5585 goto exit;
5586 }
5587 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5588 if (in->pcm_device_id < 0) {
5589 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5590 __func__, in->pcm_device_id, in->usecase);
5591 ret = -EINVAL;
5592 goto exit;
5593 }
5594
5595 adjust_mmap_period_count(&in->config, min_size_frames);
5596
5597 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5598 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5599 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5600 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305601 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305602 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5603 in->card_status = CARD_STATUS_OFFLINE;
5604 adev->card_status = CARD_STATUS_OFFLINE;
5605 ret = -EIO;
5606 goto exit;
5607 }
5608
Haynes Mathew George16081042017-05-31 17:16:49 -07005609 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5610 step = "open";
5611 ret = -ENODEV;
5612 goto exit;
5613 }
5614
5615 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5616 if (ret < 0) {
5617 step = "begin";
5618 goto exit;
5619 }
5620 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5621 info->burst_size_frames = in->config.period_size;
5622 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
5623
5624 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
5625 info->buffer_size_frames));
5626
5627 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
5628 if (ret < 0) {
5629 step = "commit";
5630 goto exit;
5631 }
5632
5633 in->standby = false;
5634 ret = 0;
5635
5636 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5637 __func__, info->shared_memory_address, info->buffer_size_frames);
5638
5639exit:
5640 if (ret != 0) {
5641 if (in->pcm == NULL) {
5642 ALOGE("%s: %s - %d", __func__, step, ret);
5643 } else {
5644 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
5645 pcm_close(in->pcm);
5646 in->pcm = NULL;
5647 }
5648 }
5649 pthread_mutex_unlock(&adev->lock);
5650 return ret;
5651}
5652
5653static int in_get_mmap_position(const struct audio_stream_in *stream,
5654 struct audio_mmap_position *position)
5655{
5656 struct stream_in *in = (struct stream_in *)stream;
5657 ALOGVV("%s", __func__);
5658 if (position == NULL) {
5659 return -EINVAL;
5660 }
5661 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
5662 return -ENOSYS;
5663 }
5664 if (in->pcm == NULL) {
5665 return -ENOSYS;
5666 }
5667 struct timespec ts = { 0, 0 };
5668 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
5669 if (ret < 0) {
5670 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
5671 return ret;
5672 }
5673 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
5674 return 0;
5675}
5676
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305677int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07005678 audio_io_handle_t handle,
5679 audio_devices_t devices,
5680 audio_output_flags_t flags,
5681 struct audio_config *config,
5682 struct audio_stream_out **stream_out,
5683 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005684{
5685 struct audio_device *adev = (struct audio_device *)dev;
5686 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305687 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005688 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005689 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05305690 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005691 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
5692 bool is_usb_dev = audio_is_usb_out_device(devices) &&
5693 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
5694 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005695
kunleizb3fb48e2018-08-20 14:40:33 +08005696 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleiz7a6d9e02018-07-30 15:38:52 +08005697 is_usb_dev = false;
5698 devices = AUDIO_DEVICE_OUT_SPEAKER;
5699 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
5700 __func__, devices);
5701 }
5702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005703 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005705 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
5706
Mingming Yin3a941d42016-02-17 18:08:05 -08005707 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
5708 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305709 devices, flags, &out->stream);
5710
5711
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005712 if (!out) {
5713 return -ENOMEM;
5714 }
5715
Haynes Mathew George204045b2015-02-25 20:32:03 -08005716 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005717 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305718 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08005719 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08005720 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5721
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005722 if (devices == AUDIO_DEVICE_NONE)
5723 devices = AUDIO_DEVICE_OUT_SPEAKER;
5724
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005725 out->flags = flags;
5726 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07005727 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07005728 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005729 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05305730 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05305731 if (out->channel_mask == AUDIO_CHANNEL_NONE)
5732 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
5733 else
5734 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07005735 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005736 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08005737 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305738 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305739 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305740 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005741 out->hal_output_suspend_supported = 0;
5742 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05305743 out->set_dual_mono = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005744
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05305745 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05305746 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07005747 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
5748
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005749 if (audio_is_linear_pcm(out->format) &&
5750 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
5751 pthread_mutex_lock(&adev->lock);
5752 if (is_hdmi) {
5753 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
5754 ret = read_hdmi_sink_caps(out);
5755 } else if (is_usb_dev) {
5756 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
5757 &config->format,
5758 &out->supported_formats[0],
5759 MAX_SUPPORTED_FORMATS,
5760 &config->channel_mask,
5761 &out->supported_channel_masks[0],
5762 MAX_SUPPORTED_CHANNEL_MASKS,
5763 &config->sample_rate,
5764 &out->supported_sample_rates[0],
5765 MAX_SUPPORTED_SAMPLE_RATES);
5766 ALOGV("plugged dev USB ret %d", ret);
5767 } else {
5768 ret = -1;
5769 }
5770 pthread_mutex_unlock(&adev->lock);
5771 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005772 if (ret == -ENOSYS) {
5773 /* ignore and go with default */
5774 ret = 0;
5775 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005776 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08005777 goto error_open;
5778 }
5779 }
5780 }
5781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005782 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07005783#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005784 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5785 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
5786 out->sample_rate == 32000 || out->sample_rate == 48000)) {
5787 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
5788 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
5789 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5790
5791 out->config = default_pcm_config_voip_copp;
5792 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5793 out->config.rate = out->sample_rate;
5794
5795#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05305796 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005797 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08005798 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005799 ret = voice_extn_compress_voip_open_output_stream(out);
5800 if (ret != 0) {
5801 ALOGE("%s: Compress voip output cannot be opened, error:%d",
5802 __func__, ret);
5803 goto error_open;
5804 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005805#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005806 } else if (audio_is_linear_pcm(out->format) &&
5807 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
5808 out->channel_mask = config->channel_mask;
5809 out->sample_rate = config->sample_rate;
5810 out->format = config->format;
5811 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
5812 // does this change?
5813 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
5814 out->config.rate = config->sample_rate;
5815 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
5816 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
5817 audio_bytes_per_sample(config->format));
5818 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07005819 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305820 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305821 pthread_mutex_lock(&adev->lock);
5822 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
5823 pthread_mutex_unlock(&adev->lock);
5824
5825 // reject offload during card offline to allow
5826 // fallback to s/w paths
5827 if (offline) {
5828 ret = -ENODEV;
5829 goto error_open;
5830 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005831
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005832 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
5833 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
5834 ALOGE("%s: Unsupported Offload information", __func__);
5835 ret = -EINVAL;
5836 goto error_open;
5837 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005838
Atul Khare3fa6e542017-08-09 00:56:17 +05305839 if (config->offload_info.format == 0)
5840 config->offload_info.format = config->format;
5841 if (config->offload_info.sample_rate == 0)
5842 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005843
Mingming Yin90310102013-11-13 16:57:00 -08005844 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305845 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07005846 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005847 ret = -EINVAL;
5848 goto error_open;
5849 }
5850
Ben Romberger0f8c87b2017-05-24 17:41:11 -07005851 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
5852 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
5853 (audio_extn_passthru_is_passthrough_stream(out)) &&
5854 !((config->sample_rate == 48000) ||
5855 (config->sample_rate == 96000) ||
5856 (config->sample_rate == 192000))) {
5857 ALOGE("%s: Unsupported sample rate %d for audio format %x",
5858 __func__, config->sample_rate, config->offload_info.format);
5859 ret = -EINVAL;
5860 goto error_open;
5861 }
5862
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005863 out->compr_config.codec = (struct snd_codec *)
5864 calloc(1, sizeof(struct snd_codec));
5865
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005866 if (!out->compr_config.codec) {
5867 ret = -ENOMEM;
5868 goto error_open;
5869 }
5870
Dhananjay Kumarac341582017-02-23 23:42:25 +05305871 out->stream.pause = out_pause;
5872 out->stream.resume = out_resume;
5873 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05305874 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305875 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07005876 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305877 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07005878 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05305879 } else {
5880 out->usecase = get_offload_usecase(adev, false /* is_compress */);
5881 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07005882 }
vivek mehta446c3962015-09-14 10:57:35 -07005883
5884 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005885 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5886 config->format == 0 && config->sample_rate == 0 &&
5887 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07005888 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08005889 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
5890 } else {
5891 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
5892 ret = -EEXIST;
5893 goto error_open;
5894 }
vivek mehta446c3962015-09-14 10:57:35 -07005895 }
5896
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005897 if (config->offload_info.channel_mask)
5898 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005899 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005900 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005901 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005902 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05305903 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005904 ret = -EINVAL;
5905 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005906 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005907
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005908 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005909 out->sample_rate = config->offload_info.sample_rate;
5910
Mingming Yin3ee55c62014-08-04 14:23:35 -07005911 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005912
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305913 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305914 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305915 audio_extn_dolby_send_ddp_endp_params(adev);
5916 audio_extn_dolby_set_dmid(adev);
5917 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005918
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005919 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08005920 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005921 out->compr_config.codec->bit_rate =
5922 config->offload_info.bit_rate;
5923 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05305924 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005925 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05305926 /* Update bit width only for non passthrough usecases.
5927 * For passthrough usecases, the output will always be opened @16 bit
5928 */
5929 if (!audio_extn_passthru_is_passthrough_stream(out))
5930 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305931
5932 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
5933 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
5934 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
5935
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005936 /*TODO: Do we need to change it for passthrough */
5937 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005938
Manish Dewangana6fc5442015-08-24 20:30:31 +05305939 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
5940 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305941 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05305942 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305943 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
5944 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305945
5946 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
5947 AUDIO_FORMAT_PCM) {
5948
5949 /*Based on platform support, configure appropriate alsa format for corresponding
5950 *hal input format.
5951 */
5952 out->compr_config.codec->format = hal_format_to_alsa(
5953 config->offload_info.format);
5954
Ashish Jain83a6cc22016-06-28 14:34:17 +05305955 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05305956 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305957 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305958
Dhananjay Kumarac341582017-02-23 23:42:25 +05305959 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05305960 *hal input format and alsa format might differ based on platform support.
5961 */
5962 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05305963 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305964
5965 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
5966
5967 /* Check if alsa session is configured with the same format as HAL input format,
5968 * if not then derive correct fragment size needed to accomodate the
5969 * conversion of HAL input format to alsa format.
5970 */
5971 audio_extn_utils_update_direct_pcm_fragment_size(out);
5972
5973 /*if hal input and output fragment size is different this indicates HAL input format is
5974 *not same as the alsa format
5975 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305976 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305977 /*Allocate a buffer to convert input data to the alsa configured format.
5978 *size of convert buffer is equal to the size required to hold one fragment size
5979 *worth of pcm data, this is because flinger does not write more than fragment_size
5980 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305981 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
5982 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05305983 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
5984 ret = -ENOMEM;
5985 goto error_open;
5986 }
5987 }
5988 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
5989 out->compr_config.fragment_size =
5990 audio_extn_passthru_get_buffer_size(&config->offload_info);
5991 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5992 } else {
5993 out->compr_config.fragment_size =
5994 platform_get_compress_offload_buffer_size(&config->offload_info);
5995 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5996 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07005997
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305998 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5999 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6000 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006001 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306002 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006003
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306004 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6005 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6006 }
6007
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006008 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6009 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006010
Manish Dewangan69426c82017-01-30 17:35:36 +05306011 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6012 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6013 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6014 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6015 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6016 } else {
6017 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6018 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006019
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306020 memset(&out->channel_map_param, 0,
6021 sizeof(struct audio_out_channel_map_param));
6022
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006023 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306024 out->send_next_track_params = false;
6025 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006026 out->offload_state = OFFLOAD_STATE_IDLE;
6027 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006028 out->writeAt.tv_sec = 0;
6029 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006030
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006031 audio_extn_dts_create_state_notifier_node(out->usecase);
6032
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006033 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6034 __func__, config->offload_info.version,
6035 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306036
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306037 /* Check if DSD audio format is supported in codec
6038 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306039 */
6040
6041 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306042 (!platform_check_codec_dsd_support(adev->platform) ||
6043 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306044 ret = -EINVAL;
6045 goto error_open;
6046 }
6047
Ashish Jain5106d362016-05-11 19:23:33 +05306048 /* Disable gapless if any of the following is true
6049 * passthrough playback
6050 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306051 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306052 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306053 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306054 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006055 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306056 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306057 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306058 check_and_set_gapless_mode(adev, false);
6059 } else
6060 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006061
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306062 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006063 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6064 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306065 if (config->format == AUDIO_FORMAT_DSD) {
6066 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6067 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6068 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006069
6070 create_offload_callback_thread(out);
6071
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006072 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306073 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006074 if (ret != 0) {
6075 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
6076 __func__, ret);
6077 goto error_open;
6078 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006079 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
6080 if (config->sample_rate == 0)
6081 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6082 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6083 config->sample_rate != 8000) {
6084 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6085 ret = -EINVAL;
6086 goto error_open;
6087 }
6088 out->sample_rate = config->sample_rate;
6089 out->config.rate = config->sample_rate;
6090 if (config->format == AUDIO_FORMAT_DEFAULT)
6091 config->format = AUDIO_FORMAT_PCM_16_BIT;
6092 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6093 config->format = AUDIO_FORMAT_PCM_16_BIT;
6094 ret = -EINVAL;
6095 goto error_open;
6096 }
6097 out->format = config->format;
6098 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
6099 out->config = pcm_config_afe_proxy_playback;
6100 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006101 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05306102 unsigned int channels = 0;
6103 /*Update config params to default if not set by the caller*/
6104 if (config->sample_rate == 0)
6105 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6106 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6107 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6108 if (config->format == AUDIO_FORMAT_DEFAULT)
6109 config->format = AUDIO_FORMAT_PCM_16_BIT;
6110
6111 channels = audio_channel_count_from_out_mask(out->channel_mask);
6112
Varun Balaraje49253e2017-07-06 19:48:56 +05306113 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6114 out->usecase = get_interactive_usecase(adev);
6115 out->config = pcm_config_low_latency;
6116 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306117 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006118 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6119 out->flags);
6120 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006121 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6122 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6123 out->config = pcm_config_mmap_playback;
6124 out->stream.start = out_start;
6125 out->stream.stop = out_stop;
6126 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6127 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306128 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6129 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006130 out->hal_output_suspend_supported =
6131 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6132 out->dynamic_pm_qos_config_supported =
6133 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6134 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006135 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6136 } else {
6137 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6138 //the mixer path will be a string similar to "low-latency-playback resume"
6139 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6140 strlcat(out->pm_qos_mixer_path,
6141 " resume", MAX_MIXER_PATH_LEN);
6142 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6143 out->pm_qos_mixer_path);
6144 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306145 out->config = pcm_config_low_latency;
6146 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6147 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6148 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306149 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6150 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6151 if (out->config.period_size <= 0) {
6152 ALOGE("Invalid configuration period size is not valid");
6153 ret = -EINVAL;
6154 goto error_open;
6155 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306156 } else {
6157 /* primary path is the default path selected if no other outputs are available/suitable */
6158 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6159 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6160 }
6161 out->hal_ip_format = format = out->format;
6162 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6163 out->hal_op_format = pcm_format_to_hal(out->config.format);
6164 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6165 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006166 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306167 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306168 if (out->hal_ip_format != out->hal_op_format) {
6169 uint32_t buffer_size = out->config.period_size *
6170 format_to_bitwidth_table[out->hal_op_format] *
6171 out->config.channels;
6172 out->convert_buffer = calloc(1, buffer_size);
6173 if (out->convert_buffer == NULL){
6174 ALOGE("Allocation failed for convert buffer for size %d",
6175 out->compr_config.fragment_size);
6176 ret = -ENOMEM;
6177 goto error_open;
6178 }
6179 ALOGD("Convert buffer allocated of size %d", buffer_size);
6180 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006181 }
6182
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006183 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6184 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306185
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006186 /* TODO remove this hardcoding and check why width is zero*/
6187 if (out->bit_width == 0)
6188 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306189 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006190 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006191 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306192 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306193 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006194 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6195 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6196 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006197 if(adev->primary_output == NULL)
6198 adev->primary_output = out;
6199 else {
6200 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006201 ret = -EEXIST;
6202 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006203 }
6204 }
6205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006206 /* Check if this usecase is already existing */
6207 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006208 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6209 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006210 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006211 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006212 ret = -EEXIST;
6213 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006214 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006215
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006216 pthread_mutex_unlock(&adev->lock);
6217
6218 out->stream.common.get_sample_rate = out_get_sample_rate;
6219 out->stream.common.set_sample_rate = out_set_sample_rate;
6220 out->stream.common.get_buffer_size = out_get_buffer_size;
6221 out->stream.common.get_channels = out_get_channels;
6222 out->stream.common.get_format = out_get_format;
6223 out->stream.common.set_format = out_set_format;
6224 out->stream.common.standby = out_standby;
6225 out->stream.common.dump = out_dump;
6226 out->stream.common.set_parameters = out_set_parameters;
6227 out->stream.common.get_parameters = out_get_parameters;
6228 out->stream.common.add_audio_effect = out_add_audio_effect;
6229 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6230 out->stream.get_latency = out_get_latency;
6231 out->stream.set_volume = out_set_volume;
6232 out->stream.write = out_write;
6233 out->stream.get_render_position = out_get_render_position;
6234 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006235 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006236
Haynes Mathew George16081042017-05-31 17:16:49 -07006237 if (out->realtime)
6238 out->af_period_multiplier = af_period_multiplier;
6239 else
6240 out->af_period_multiplier = 1;
6241
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006242 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006243 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006244 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006245
6246 config->format = out->stream.common.get_format(&out->stream.common);
6247 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6248 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
6249
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306250 /*
6251 By locking output stream before registering, we allow the callback
6252 to update stream's state only after stream's initial state is set to
6253 adev state.
6254 */
6255 lock_output_stream(out);
6256 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6257 pthread_mutex_lock(&adev->lock);
6258 out->card_status = adev->card_status;
6259 pthread_mutex_unlock(&adev->lock);
6260 pthread_mutex_unlock(&out->lock);
6261
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006262 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306263 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006264 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006265
6266 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6267 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6268 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006269 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306270 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006271 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006272 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306273 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006274 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6275 out->usecase, PCM_PLAYBACK);
6276 hdlr_stream_cfg.flags = out->flags;
6277 hdlr_stream_cfg.type = PCM_PLAYBACK;
6278 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6279 &hdlr_stream_cfg);
6280 if (ret) {
6281 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6282 out->adsp_hdlr_stream_handle = NULL;
6283 }
6284 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306285 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006286 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006287 if (ret < 0) {
6288 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6289 out->ip_hdlr_handle = NULL;
6290 }
6291 }
Eric Laurent994a6932013-07-17 11:51:42 -07006292 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006293 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006294
6295error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306296 if (out->convert_buffer)
6297 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006298 free(out);
6299 *stream_out = NULL;
6300 ALOGD("%s: exit: ret %d", __func__, ret);
6301 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006302}
6303
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306304void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006305 struct audio_stream_out *stream)
6306{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006307 struct stream_out *out = (struct stream_out *)stream;
6308 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006309 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006310
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006311 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306312
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306313 // must deregister from sndmonitor first to prevent races
6314 // between the callback and close_stream
6315 audio_extn_snd_mon_unregister_listener(out);
6316
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006317 /* close adsp hdrl session before standby */
6318 if (out->adsp_hdlr_stream_handle) {
6319 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6320 if (ret)
6321 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6322 out->adsp_hdlr_stream_handle = NULL;
6323 }
6324
Manish Dewangan21a850a2017-08-14 12:03:55 +05306325 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006326 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6327 out->ip_hdlr_handle = NULL;
6328 }
6329
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006330 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306331 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006332 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306333 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306334 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006335 if(ret != 0)
6336 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6337 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006338 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006339 out_standby(&stream->common);
6340
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006341 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006342 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006343 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006344 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006345 if (out->compr_config.codec != NULL)
6346 free(out->compr_config.codec);
6347 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006348
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306349 out->a2dp_compress_mute = false;
6350
Varun Balaraje49253e2017-07-06 19:48:56 +05306351 if (is_interactive_usecase(out->usecase))
6352 free_interactive_usecase(adev, out->usecase);
6353
Ashish Jain83a6cc22016-06-28 14:34:17 +05306354 if (out->convert_buffer != NULL) {
6355 free(out->convert_buffer);
6356 out->convert_buffer = NULL;
6357 }
6358
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006359 if (adev->voice_tx_output == out)
6360 adev->voice_tx_output = NULL;
6361
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306362 if (adev->primary_output == out)
6363 adev->primary_output = NULL;
6364
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006365 pthread_cond_destroy(&out->cond);
6366 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006367 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006368 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006369}
6370
6371static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6372{
6373 struct audio_device *adev = (struct audio_device *)dev;
6374 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006375 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006376 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006377 int ret;
6378 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006379
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006380 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006381 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006382
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306383 if (!parms)
6384 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306385
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306386 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6387 if (ret >= 0) {
6388 /* When set to false, HAL should disable EC and NS */
6389 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6390 adev->bt_sco_on = true;
6391 else
6392 adev->bt_sco_on = false;
6393 }
6394
Naresh Tanniru4c630392014-05-12 01:05:52 +05306395 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006396 status = voice_set_parameters(adev, parms);
6397 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006398 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006399
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006400 status = platform_set_parameters(adev->platform, parms);
6401 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006402 goto done;
6403
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006404 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6405 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006406 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006407 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6408 adev->bluetooth_nrec = true;
6409 else
6410 adev->bluetooth_nrec = false;
6411 }
6412
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006413 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6414 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006415 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6416 adev->screen_off = false;
6417 else
6418 adev->screen_off = true;
6419 }
6420
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006421 ret = str_parms_get_int(parms, "rotation", &val);
6422 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006423 bool reverse_speakers = false;
6424 switch(val) {
6425 // FIXME: note that the code below assumes that the speakers are in the correct placement
6426 // relative to the user when the device is rotated 90deg from its default rotation. This
6427 // assumption is device-specific, not platform-specific like this code.
6428 case 270:
6429 reverse_speakers = true;
6430 break;
6431 case 0:
6432 case 90:
6433 case 180:
6434 break;
6435 default:
6436 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006437 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006438 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006439 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006440 // check and set swap
6441 // - check if orientation changed and speaker active
6442 // - set rotation and cache the rotation value
6443 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006444 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006445 }
6446
Mingming Yin514a8bc2014-07-29 15:22:21 -07006447 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6448 if (ret >= 0) {
6449 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6450 adev->bt_wb_speech_enabled = true;
6451 else
6452 adev->bt_wb_speech_enabled = false;
6453 }
6454
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006455 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6456 if (ret >= 0) {
6457 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306458 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08006459 if (audio_is_output_device(val) &&
6460 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006461 ALOGV("cache new ext disp type and edid");
6462 ret = platform_get_ext_disp_type(adev->platform);
6463 if (ret < 0) {
6464 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08006465 status = ret;
6466 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006467 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006468 platform_cache_edid(adev->platform);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306469 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07006470 /*
6471 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6472 * Per AudioPolicyManager, USB device is higher priority than WFD.
6473 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6474 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6475 * starting voice call on USB
6476 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006477 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306478 if (ret >= 0)
6479 audio_extn_usb_add_device(device, atoi(value));
6480
Zhou Song6f862822017-11-06 17:27:57 +08006481 if (!audio_extn_usb_is_tunnel_supported()) {
6482 ALOGV("detected USB connect .. disable proxy");
6483 adev->allow_afe_proxy_usage = false;
6484 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006485 }
6486 }
6487
6488 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6489 if (ret >= 0) {
6490 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306491 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07006492 /*
6493 * The HDMI / Displayport disconnect handling has been moved to
6494 * audio extension to ensure that its parameters are not
6495 * invalidated prior to updating sysfs of the disconnect event
6496 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6497 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306498 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006499 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306500 if (ret >= 0)
6501 audio_extn_usb_remove_device(device, atoi(value));
6502
Zhou Song6f862822017-11-06 17:27:57 +08006503 if (!audio_extn_usb_is_tunnel_supported()) {
6504 ALOGV("detected USB disconnect .. enable proxy");
6505 adev->allow_afe_proxy_usage = true;
6506 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006507 }
6508 }
6509
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306510 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6511 if (ret >= 0) {
6512 struct audio_usecase *usecase;
6513 struct listnode *node;
6514 list_for_each(node, &adev->usecase_list) {
6515 usecase = node_to_item(node, struct audio_usecase, list);
6516 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07006517 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306518 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08006519
6520 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306521 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08006522 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306523 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306524 //force device switch to re configure encoder
6525 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306526 audio_extn_a2dp_set_handoff_mode(false);
6527 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306528 break;
6529 }
6530 }
6531 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006532
6533 //handle vr audio setparam
6534 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6535 value, sizeof(value));
6536 if (ret >= 0) {
6537 ALOGI("Setting vr mode to be %s", value);
6538 if (!strncmp(value, "true", 4)) {
6539 adev->vr_audio_mode_enabled = true;
6540 ALOGI("Setting vr mode to true");
6541 } else if (!strncmp(value, "false", 5)) {
6542 adev->vr_audio_mode_enabled = false;
6543 ALOGI("Setting vr mode to false");
6544 } else {
6545 ALOGI("wrong vr mode set");
6546 }
6547 }
6548
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306549 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006550done:
6551 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006552 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306553error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006554 ALOGV("%s: exit with code(%d)", __func__, status);
6555 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006556}
6557
6558static char* adev_get_parameters(const struct audio_hw_device *dev,
6559 const char *keys)
6560{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006561 struct audio_device *adev = (struct audio_device *)dev;
6562 struct str_parms *reply = str_parms_create();
6563 struct str_parms *query = str_parms_create_str(keys);
6564 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05306565 char value[256] = {0};
6566 int ret = 0;
6567
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006568 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006569 if (reply) {
6570 str_parms_destroy(reply);
6571 }
6572 if (query) {
6573 str_parms_destroy(query);
6574 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006575 ALOGE("adev_get_parameters: failed to create query or reply");
6576 return NULL;
6577 }
6578
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006579 //handle vr audio getparam
6580
6581 ret = str_parms_get_str(query,
6582 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6583 value, sizeof(value));
6584
6585 if (ret >= 0) {
6586 bool vr_audio_enabled = false;
6587 pthread_mutex_lock(&adev->lock);
6588 vr_audio_enabled = adev->vr_audio_mode_enabled;
6589 pthread_mutex_unlock(&adev->lock);
6590
6591 ALOGI("getting vr mode to %d", vr_audio_enabled);
6592
6593 if (vr_audio_enabled) {
6594 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6595 "true");
6596 goto exit;
6597 } else {
6598 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6599 "false");
6600 goto exit;
6601 }
6602 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006603
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006604 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006605 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08006606 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006607 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05306608 pthread_mutex_unlock(&adev->lock);
6609
Naresh Tannirud7205b62014-06-20 02:54:48 +05306610exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006611 str = str_parms_to_str(reply);
6612 str_parms_destroy(query);
6613 str_parms_destroy(reply);
6614
6615 ALOGV("%s: exit: returns - %s", __func__, str);
6616 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006617}
6618
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006619static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006620{
6621 return 0;
6622}
6623
6624static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
6625{
Haynes Mathew George5191a852013-09-11 14:19:36 -07006626 int ret;
6627 struct audio_device *adev = (struct audio_device *)dev;
6628 pthread_mutex_lock(&adev->lock);
6629 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07006630 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07006631 pthread_mutex_unlock(&adev->lock);
6632 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006633}
6634
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006635static int adev_set_master_volume(struct audio_hw_device *dev __unused,
6636 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006637{
6638 return -ENOSYS;
6639}
6640
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006641static int adev_get_master_volume(struct audio_hw_device *dev __unused,
6642 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006643{
6644 return -ENOSYS;
6645}
6646
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006647static int adev_set_master_mute(struct audio_hw_device *dev __unused,
6648 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006649{
6650 return -ENOSYS;
6651}
6652
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006653static int adev_get_master_mute(struct audio_hw_device *dev __unused,
6654 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006655{
6656 return -ENOSYS;
6657}
6658
6659static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
6660{
6661 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006663 pthread_mutex_lock(&adev->lock);
6664 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006665 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006666 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08006667 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006668 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07006669 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006670 adev->current_call_output = NULL;
6671 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006672 }
6673 pthread_mutex_unlock(&adev->lock);
6674 return 0;
6675}
6676
6677static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
6678{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006679 int ret;
6680
6681 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08006682 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006683 ret = voice_set_mic_mute((struct audio_device *)dev, state);
6684 pthread_mutex_unlock(&adev->lock);
6685
6686 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006687}
6688
6689static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
6690{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006691 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006692 return 0;
6693}
6694
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006695static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006696 const struct audio_config *config)
6697{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006698 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006699
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006700 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
6701 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006702}
6703
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006704static bool adev_input_allow_hifi_record(struct audio_device *adev,
6705 audio_devices_t devices,
6706 audio_input_flags_t flags,
6707 audio_source_t source) {
6708 const bool allowed = true;
6709
6710 if (!audio_is_usb_in_device(devices))
6711 return !allowed;
6712
6713 switch (flags) {
6714 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006715 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07006716 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
6717 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006718 default:
6719 return !allowed;
6720 }
6721
6722 switch (source) {
6723 case AUDIO_SOURCE_DEFAULT:
6724 case AUDIO_SOURCE_MIC:
6725 case AUDIO_SOURCE_UNPROCESSED:
6726 break;
6727 default:
6728 return !allowed;
6729 }
6730
6731 switch (adev->mode) {
6732 case 0:
6733 break;
6734 default:
6735 return !allowed;
6736 }
6737
6738 return allowed;
6739}
6740
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006741static int adev_update_voice_comm_input_stream(struct stream_in *in,
6742 struct audio_config *config)
6743{
6744 bool valid_rate = (config->sample_rate == 8000 ||
6745 config->sample_rate == 16000 ||
6746 config->sample_rate == 32000 ||
6747 config->sample_rate == 48000);
6748 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
6749
6750#ifndef COMPRESS_VOIP_ENABLED
kunleiz67646da2018-04-09 11:12:32 +08006751 if (valid_rate && valid_ch &&
6752 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006753 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6754 in->config = default_pcm_config_voip_copp;
6755 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
6756 DEFAULT_VOIP_BUF_DURATION_MS,
6757 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6758 } else {
kunleiz99754d02018-04-24 10:53:17 +08006759 ALOGW("%s No valid input in voip, use defaults"
6760 "sample rate %u, channel mask 0x%X",
6761 __func__, config->sample_rate, in->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006762 }
6763 in->config.rate = config->sample_rate;
6764 in->sample_rate = config->sample_rate;
6765#else
6766 //XXX needed for voice_extn_compress_voip_open_input_stream
6767 in->config.rate = config->sample_rate;
6768 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6769 voice_extn_compress_voip_is_active(in->dev)) &&
6770 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6771 valid_rate && valid_ch) {
6772 voice_extn_compress_voip_open_input_stream(in);
6773 // update rate entries to match config from AF
6774 in->config.rate = config->sample_rate;
6775 in->sample_rate = config->sample_rate;
6776 } else {
6777 ALOGW("%s compress voip not active, use defaults", __func__);
6778 }
6779#endif
6780 return 0;
6781}
6782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006783static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006784 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006785 audio_devices_t devices,
6786 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006787 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306788 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006789 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006790 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006791{
6792 struct audio_device *adev = (struct audio_device *)dev;
6793 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006794 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006795 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006796 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306797 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006798 bool is_usb_dev = audio_is_usb_in_device(devices);
6799 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
6800 devices,
6801 flags,
6802 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306803
kunleizb3fb48e2018-08-20 14:40:33 +08006804 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleiz7a6d9e02018-07-30 15:38:52 +08006805 is_usb_dev = false;
6806 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
6807 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
6808 __func__, devices);
6809 }
6810
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006811 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006812
6813 if (!(is_usb_dev && may_use_hifi_record)) {
6814 if (config->sample_rate == 0)
6815 config->sample_rate = 48000;
6816 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6817 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
6818 if (config->format == AUDIO_FORMAT_DEFAULT)
6819 config->format = AUDIO_FORMAT_PCM_16_BIT;
6820
6821 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
6822
6823 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
6824 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05306825 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006826
6827 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006828
6829 if (!in) {
6830 ALOGE("failed to allocate input stream");
6831 return -ENOMEM;
6832 }
6833
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306834 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306835 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
6836 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006837 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006838 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006839
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006840 in->stream.common.get_sample_rate = in_get_sample_rate;
6841 in->stream.common.set_sample_rate = in_set_sample_rate;
6842 in->stream.common.get_buffer_size = in_get_buffer_size;
6843 in->stream.common.get_channels = in_get_channels;
6844 in->stream.common.get_format = in_get_format;
6845 in->stream.common.set_format = in_set_format;
6846 in->stream.common.standby = in_standby;
6847 in->stream.common.dump = in_dump;
6848 in->stream.common.set_parameters = in_set_parameters;
6849 in->stream.common.get_parameters = in_get_parameters;
6850 in->stream.common.add_audio_effect = in_add_audio_effect;
6851 in->stream.common.remove_audio_effect = in_remove_audio_effect;
6852 in->stream.set_gain = in_set_gain;
6853 in->stream.read = in_read;
6854 in->stream.get_input_frames_lost = in_get_input_frames_lost;
6855
6856 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006857 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006858 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006859 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006860 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006861 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07006862 in->bit_width = 16;
6863 in->af_period_multiplier = 1;
6864
6865 /* Update config params with the requested sample rate and channels */
6866 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
6867 (adev->mode != AUDIO_MODE_IN_CALL)) {
6868 ret = -EINVAL;
6869 goto err_open;
6870 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006871
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006872 if (is_usb_dev && may_use_hifi_record) {
6873 /* HiFi record selects an appropriate format, channel, rate combo
6874 depending on sink capabilities*/
6875 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
6876 &config->format,
6877 &in->supported_formats[0],
6878 MAX_SUPPORTED_FORMATS,
6879 &config->channel_mask,
6880 &in->supported_channel_masks[0],
6881 MAX_SUPPORTED_CHANNEL_MASKS,
6882 &config->sample_rate,
6883 &in->supported_sample_rates[0],
6884 MAX_SUPPORTED_SAMPLE_RATES);
6885 if (ret != 0) {
6886 ret = -EINVAL;
6887 goto err_open;
6888 }
6889 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006890 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306891 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05306892 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
6893 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
6894 in->config.format = PCM_FORMAT_S32_LE;
6895 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306896 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
6897 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
6898 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
6899 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6900 bool ret_error = false;
6901 in->bit_width = 24;
6902 /* 24 bit is restricted to UNPROCESSED source only,also format supported
6903 from HAL is 24_packed and 8_24
6904 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
6905 24_packed return error indicating supported format is 24_packed
6906 *> In case of any other source requesting 24 bit or float return error
6907 indicating format supported is 16 bit only.
6908
6909 on error flinger will retry with supported format passed
6910 */
6911 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
6912 (source != AUDIO_SOURCE_CAMCORDER)) {
6913 config->format = AUDIO_FORMAT_PCM_16_BIT;
6914 if (config->sample_rate > 48000)
6915 config->sample_rate = 48000;
6916 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07006917 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
6918 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306919 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
6920 ret_error = true;
6921 }
6922
6923 if (ret_error) {
6924 ret = -EINVAL;
6925 goto err_open;
6926 }
6927 }
6928
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006929 in->channel_mask = config->channel_mask;
6930 in->format = config->format;
6931
6932 in->usecase = USECASE_AUDIO_RECORD;
6933 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
6934 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
6935 is_low_latency = true;
6936#if LOW_LATENCY_CAPTURE_USE_CASE
6937 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
6938#endif
6939 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
6940 }
6941
6942 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
6943 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
6944 in->realtime = 0;
6945 in->usecase = USECASE_AUDIO_RECORD_MMAP;
6946 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07006947 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006948 in->stream.start = in_start;
6949 in->stream.stop = in_stop;
6950 in->stream.create_mmap_buffer = in_create_mmap_buffer;
6951 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georged2d7bc32018-01-31 12:48:20 -08006952 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006953 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
6954 } else if (in->realtime) {
6955 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07006956 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006957 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006958 in->sample_rate = in->config.rate;
6959 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07006960 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006961 in->usecase = USECASE_AUDIO_RECORD_HIFI;
6962 in->config = pcm_config_audio_capture;
6963 frame_size = audio_stream_in_frame_size(&in->stream);
6964 buffer_size = get_input_buffer_size(config->sample_rate,
6965 config->format,
6966 channel_count,
6967 false /*is_low_latency*/);
6968 in->config.period_size = buffer_size / frame_size;
6969 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006970 in->config.format = pcm_format_from_audio_format(config->format);
6971 in->config.channels = channel_count;
Haynes Mathew Georged2d7bc32018-01-31 12:48:20 -08006972 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006973 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05306974 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006975 if (config->sample_rate == 0)
6976 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6977 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6978 config->sample_rate != 8000) {
6979 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6980 ret = -EINVAL;
6981 goto err_open;
6982 }
6983 if (config->format == AUDIO_FORMAT_DEFAULT)
6984 config->format = AUDIO_FORMAT_PCM_16_BIT;
6985 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6986 config->format = AUDIO_FORMAT_PCM_16_BIT;
6987 ret = -EINVAL;
6988 goto err_open;
6989 }
6990
6991 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
6992 in->config = pcm_config_afe_proxy_record;
6993 in->config.channels = channel_count;
6994 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306995 in->sample_rate = config->sample_rate;
Haynes Mathew George46740472017-10-27 18:40:12 -07006996 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05306997 int ret_val;
6998 pthread_mutex_lock(&adev->lock);
6999 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
7000 in, config, &channel_mask_updated);
7001 pthread_mutex_unlock(&adev->lock);
7002
7003 if (!ret_val) {
7004 if (channel_mask_updated == true) {
7005 ALOGD("%s: return error to retry with updated channel mask (%#x)",
7006 __func__, config->channel_mask);
7007 ret = -EINVAL;
7008 goto err_open;
7009 }
7010 ALOGD("%s: created multi-channel session succesfully",__func__);
7011 } else if (audio_extn_compr_cap_enabled() &&
7012 audio_extn_compr_cap_format_supported(config->format) &&
7013 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
7014 audio_extn_compr_cap_init(in);
7015 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05307016 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05307017 ret = audio_extn_cin_configure_input_stream(in);
7018 if (ret)
7019 goto err_open;
7020 } else {
7021 in->config = pcm_config_audio_capture;
7022 in->config.rate = config->sample_rate;
7023 in->config.format = pcm_format_from_audio_format(config->format);
7024 in->config.channels = channel_count;
7025 in->sample_rate = config->sample_rate;
7026 in->format = config->format;
7027 frame_size = audio_stream_in_frame_size(&in->stream);
7028 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07007029 config->format,
7030 channel_count,
7031 is_low_latency);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307032 in->config.period_size = buffer_size / frame_size;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007033
Revathi Uddarajud2634032017-12-07 14:42:34 +05307034 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
7035 /* optionally use VOIP usecase depending on config(s) */
7036 ret = adev_update_voice_comm_input_stream(in, config);
7037 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007038
Revathi Uddarajud2634032017-12-07 14:42:34 +05307039 if (ret) {
7040 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
7041 goto err_open;
7042 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007043 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007044 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307045 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7046 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007047 devices, flags, in->format,
7048 in->sample_rate, in->bit_width,
7049 in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307050
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007051 /* This stream could be for sound trigger lab,
7052 get sound trigger pcm if present */
7053 audio_extn_sound_trigger_check_and_get_session(in);
7054
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307055 lock_input_stream(in);
7056 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
7057 pthread_mutex_lock(&adev->lock);
7058 in->card_status = adev->card_status;
7059 pthread_mutex_unlock(&adev->lock);
7060 pthread_mutex_unlock(&in->lock);
7061
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007062 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07007063 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007064 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007065
7066err_open:
7067 free(in);
7068 *stream_in = NULL;
7069 return ret;
7070}
7071
7072static void adev_close_input_stream(struct audio_hw_device *dev,
7073 struct audio_stream_in *stream)
7074{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007075 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007076 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007077 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307078
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307079 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007080
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307081 // must deregister from sndmonitor first to prevent races
7082 // between the callback and close_stream
7083 audio_extn_snd_mon_unregister_listener(stream);
7084
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307085 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07007086 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307087
Pallavid7c7a272018-01-16 11:22:55 +05307088 if (in == NULL) {
7089 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
7090 return;
7091 }
7092
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007093 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307094 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007095 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307096 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007097 if (ret != 0)
7098 ALOGE("%s: Compress voip input cannot be closed, error:%d",
7099 __func__, ret);
7100 } else
7101 in_standby(&stream->common);
7102
Revathi Uddarajud2634032017-12-07 14:42:34 +05307103 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07007104 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007105 audio_extn_ssr_deinit();
7106 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007107
Garmond Leunge2433c32017-09-28 21:51:22 -07007108 if (audio_extn_ffv_get_stream() == in) {
7109 audio_extn_ffv_stream_deinit();
7110 }
7111
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307112 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07007113 audio_extn_compr_cap_format_supported(in->config.format))
7114 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05307115
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307116 if (audio_extn_cin_attached_usecase(in->usecase))
7117 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007118
Mingming Yinfd7607b2016-01-22 12:48:44 -08007119 if (in->is_st_session) {
7120 ALOGV("%s: sound trigger pcm stop lab", __func__);
7121 audio_extn_sound_trigger_stop_lab(in);
7122 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007123 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307124 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007125 return;
7126}
7127
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307128int adev_create_audio_patch(struct audio_hw_device *dev,
7129 unsigned int num_sources,
7130 const struct audio_port_config *sources,
7131 unsigned int num_sinks,
7132 const struct audio_port_config *sinks,
7133 audio_patch_handle_t *handle)
7134{
7135
7136
7137 return audio_extn_hw_loopback_create_audio_patch(dev,
7138 num_sources,
7139 sources,
7140 num_sinks,
7141 sinks,
7142 handle);
7143
7144}
7145
7146int adev_release_audio_patch(struct audio_hw_device *dev,
7147 audio_patch_handle_t handle)
7148{
7149 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
7150}
7151
7152int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
7153{
7154 return audio_extn_hw_loopback_get_audio_port(dev, config);
7155}
7156
7157int adev_set_audio_port_config(struct audio_hw_device *dev,
7158 const struct audio_port_config *config)
7159{
7160 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
7161}
7162
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007163static int adev_dump(const audio_hw_device_t *device __unused,
7164 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007165{
7166 return 0;
7167}
7168
7169static int adev_close(hw_device_t *device)
7170{
7171 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07007172
7173 if (!adev)
7174 return 0;
7175
7176 pthread_mutex_lock(&adev_init_lock);
7177
7178 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307179 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007180 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08007181 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307182 audio_extn_utils_release_streams_cfg_lists(
7183 &adev->streams_output_cfg_list,
7184 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307185 if (audio_extn_qaf_is_enabled())
7186 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007187 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007188 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007189 free(adev->snd_dev_ref_cnt);
7190 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007191 if (adev->adm_deinit)
7192 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307193 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007194 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307195 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307196 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007197 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307198 if (adev->device_cfg_params) {
7199 free(adev->device_cfg_params);
7200 adev->device_cfg_params = NULL;
7201 }
Kiran Kandi910e1862013-10-29 13:29:42 -07007202 free(device);
7203 adev = NULL;
7204 }
7205 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007207 return 0;
7208}
7209
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007210/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
7211 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
7212 * just that it _might_ work.
7213 */
7214static int period_size_is_plausible_for_low_latency(int period_size)
7215{
7216 switch (period_size) {
7217 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07007218 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007219 case 240:
7220 case 320:
7221 case 480:
7222 return 1;
7223 default:
7224 return 0;
7225 }
7226}
7227
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307228static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
7229{
7230 bool is_snd_card_status = false;
7231 bool is_ext_device_status = false;
7232 char value[32];
7233 int card = -1;
7234 card_status_t status;
7235
7236 if (cookie != adev || !parms)
7237 return;
7238
7239 if (!parse_snd_card_status(parms, &card, &status)) {
7240 is_snd_card_status = true;
7241 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
7242 is_ext_device_status = true;
7243 } else {
7244 // not a valid event
7245 return;
7246 }
7247
7248 pthread_mutex_lock(&adev->lock);
7249 if (card == adev->snd_card || is_ext_device_status) {
7250 if (is_snd_card_status && adev->card_status != status) {
7251 adev->card_status = status;
7252 platform_snd_card_update(adev->platform, status);
7253 audio_extn_fm_set_parameters(adev, parms);
7254 } else if (is_ext_device_status) {
7255 platform_set_parameters(adev->platform, parms);
7256 }
7257 }
7258 pthread_mutex_unlock(&adev->lock);
7259 return;
7260}
7261
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307262/* out and adev lock held */
7263static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
7264{
7265 struct audio_usecase *uc_info;
7266 float left_p;
7267 float right_p;
7268 audio_devices_t devices;
7269
7270 uc_info = get_usecase_from_list(adev, out->usecase);
7271 if (uc_info == NULL) {
7272 ALOGE("%s: Could not find the usecase (%d) in the list",
7273 __func__, out->usecase);
7274 return -EINVAL;
7275 }
7276
7277 ALOGD("%s: enter: usecase(%d: %s)", __func__,
7278 out->usecase, use_case_table[out->usecase]);
7279
7280 if (restore) {
7281 // restore A2DP device for active usecases and unmute if required
7282 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
7283 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
7284 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
7285 select_devices(adev, uc_info->id);
7286 pthread_mutex_lock(&out->compr_mute_lock);
7287 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7288 (out->a2dp_compress_mute)) {
7289 out->a2dp_compress_mute = false;
7290 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
7291 }
7292 pthread_mutex_unlock(&out->compr_mute_lock);
7293 }
7294 } else {
7295 // mute compress stream if suspended
7296 pthread_mutex_lock(&out->compr_mute_lock);
7297 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7298 (!out->a2dp_compress_mute)) {
7299 if (!out->standby) {
7300 ALOGD("%s: selecting speaker and muting stream", __func__);
7301 devices = out->devices;
7302 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
7303 left_p = out->volume_l;
7304 right_p = out->volume_r;
7305 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7306 compress_pause(out->compr);
7307 out_set_compr_volume(&out->stream, (float)0, (float)0);
7308 out->a2dp_compress_mute = true;
7309 select_devices(adev, out->usecase);
7310 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7311 compress_resume(out->compr);
7312 out->devices = devices;
7313 out->volume_l = left_p;
7314 out->volume_r = right_p;
7315 }
7316 }
7317 pthread_mutex_unlock(&out->compr_mute_lock);
7318 }
7319 ALOGV("%s: exit", __func__);
7320 return 0;
7321}
7322
7323int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
7324{
7325 int ret = 0;
7326
7327 lock_output_stream(out);
7328 pthread_mutex_lock(&adev->lock);
7329
7330 ret = check_a2dp_restore_l(adev, out, restore);
7331
7332 pthread_mutex_unlock(&adev->lock);
7333 pthread_mutex_unlock(&out->lock);
7334 return ret;
7335}
7336
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007337static int adev_open(const hw_module_t *module, const char *name,
7338 hw_device_t **device)
7339{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307340 int ret;
7341
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007342 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007343 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
7344
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007345 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07007346 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007347 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07007348 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007349 ALOGD("%s: returning existing instance of adev", __func__);
7350 ALOGD("%s: exit", __func__);
7351 pthread_mutex_unlock(&adev_init_lock);
7352 return 0;
7353 }
7354
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007355 adev = calloc(1, sizeof(struct audio_device));
7356
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007357 if (!adev) {
7358 pthread_mutex_unlock(&adev_init_lock);
7359 return -ENOMEM;
7360 }
7361
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007362 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
7363
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05307364#ifdef DYNAMIC_LOG_ENABLED
7365 register_for_dynamic_logging("hal");
7366#endif
7367
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007368 adev->device.common.tag = HARDWARE_DEVICE_TAG;
7369 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7370 adev->device.common.module = (struct hw_module_t *)module;
7371 adev->device.common.close = adev_close;
7372
7373 adev->device.init_check = adev_init_check;
7374 adev->device.set_voice_volume = adev_set_voice_volume;
7375 adev->device.set_master_volume = adev_set_master_volume;
7376 adev->device.get_master_volume = adev_get_master_volume;
7377 adev->device.set_master_mute = adev_set_master_mute;
7378 adev->device.get_master_mute = adev_get_master_mute;
7379 adev->device.set_mode = adev_set_mode;
7380 adev->device.set_mic_mute = adev_set_mic_mute;
7381 adev->device.get_mic_mute = adev_get_mic_mute;
7382 adev->device.set_parameters = adev_set_parameters;
7383 adev->device.get_parameters = adev_get_parameters;
7384 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
7385 adev->device.open_output_stream = adev_open_output_stream;
7386 adev->device.close_output_stream = adev_close_output_stream;
7387 adev->device.open_input_stream = adev_open_input_stream;
7388 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307389 adev->device.create_audio_patch = adev_create_audio_patch;
7390 adev->device.release_audio_patch = adev_release_audio_patch;
7391 adev->device.get_audio_port = adev_get_audio_port;
7392 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007393 adev->device.dump = adev_dump;
7394
7395 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007396 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08007397 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007398 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007399 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007400 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08007401 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07007402 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307403 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07007404 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07007405 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007406 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08007407 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08007408 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007409 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05307410 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307411 adev->perf_lock_opts[0] = 0x101;
7412 adev->perf_lock_opts[1] = 0x20E;
7413 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007414 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307415
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007416 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07007417 adev->platform = platform_init(adev);
7418 if (!adev->platform) {
7419 free(adev->snd_dev_ref_cnt);
7420 free(adev);
7421 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7422 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08007423 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307424 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007425 return -EINVAL;
7426 }
Eric Laurentc4aef752013-09-12 17:45:53 -07007427
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307428 if (audio_extn_qaf_is_enabled()) {
7429 ret = audio_extn_qaf_init(adev);
7430 if (ret < 0) {
7431 free(adev);
7432 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7433 *device = NULL;
7434 pthread_mutex_unlock(&adev_init_lock);
7435 pthread_mutex_destroy(&adev->lock);
7436 return ret;
7437 }
7438
7439 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
7440 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
7441 }
7442
Eric Laurentc4aef752013-09-12 17:45:53 -07007443 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
7444 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
7445 if (adev->visualizer_lib == NULL) {
7446 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
7447 } else {
7448 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
7449 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007450 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007451 "visualizer_hal_start_output");
7452 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007453 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007454 "visualizer_hal_stop_output");
7455 }
7456 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05307457 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08007458 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007459 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307460 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007461 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07007462
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007463 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
7464 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
7465 if (adev->offload_effects_lib == NULL) {
7466 ALOGE("%s: DLOPEN failed for %s", __func__,
7467 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7468 } else {
7469 ALOGV("%s: DLOPEN successful for %s", __func__,
7470 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7471 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05307472 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007473 "offload_effects_bundle_hal_start_output");
7474 adev->offload_effects_stop_output =
7475 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
7476 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007477 adev->offload_effects_set_hpx_state =
7478 (int (*)(bool))dlsym(adev->offload_effects_lib,
7479 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05307480 adev->offload_effects_get_parameters =
7481 (void (*)(struct str_parms *, struct str_parms *))
7482 dlsym(adev->offload_effects_lib,
7483 "offload_effects_bundle_get_parameters");
7484 adev->offload_effects_set_parameters =
7485 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
7486 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007487 }
7488 }
7489
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007490 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
7491 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
7492 if (adev->adm_lib == NULL) {
7493 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
7494 } else {
7495 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
7496 adev->adm_init = (adm_init_t)
7497 dlsym(adev->adm_lib, "adm_init");
7498 adev->adm_deinit = (adm_deinit_t)
7499 dlsym(adev->adm_lib, "adm_deinit");
7500 adev->adm_register_input_stream = (adm_register_input_stream_t)
7501 dlsym(adev->adm_lib, "adm_register_input_stream");
7502 adev->adm_register_output_stream = (adm_register_output_stream_t)
7503 dlsym(adev->adm_lib, "adm_register_output_stream");
7504 adev->adm_deregister_stream = (adm_deregister_stream_t)
7505 dlsym(adev->adm_lib, "adm_deregister_stream");
7506 adev->adm_request_focus = (adm_request_focus_t)
7507 dlsym(adev->adm_lib, "adm_request_focus");
7508 adev->adm_abandon_focus = (adm_abandon_focus_t)
7509 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007510 adev->adm_set_config = (adm_set_config_t)
7511 dlsym(adev->adm_lib, "adm_set_config");
7512 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
7513 dlsym(adev->adm_lib, "adm_request_focus_v2");
7514 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
7515 dlsym(adev->adm_lib, "adm_is_noirq_avail");
7516 adev->adm_on_routing_change = (adm_on_routing_change_t)
7517 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007518 }
7519 }
7520
Mingming Yin514a8bc2014-07-29 15:22:21 -07007521 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007522 //initialize this to false for now,
7523 //this will be set to true through set param
7524 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07007525
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07007526 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007527 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007528 adev->dsp_bit_width_enforce_mode =
7529 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007530
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307531 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
7532 &adev->streams_output_cfg_list,
7533 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007534
Kiran Kandi910e1862013-10-29 13:29:42 -07007535 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007536
7537 char value[PROPERTY_VALUE_MAX];
7538 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007539 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007540 trial = atoi(value);
7541 if (period_size_is_plausible_for_low_latency(trial)) {
7542 pcm_config_low_latency.period_size = trial;
7543 pcm_config_low_latency.start_threshold = trial / 4;
7544 pcm_config_low_latency.avail_min = trial / 4;
7545 configured_low_latency_capture_period_size = trial;
7546 }
7547 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007548 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007549 trial = atoi(value);
7550 if (period_size_is_plausible_for_low_latency(trial)) {
7551 configured_low_latency_capture_period_size = trial;
7552 }
7553 }
7554
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007555 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007556 af_period_multiplier = atoi(value);
7557 if (af_period_multiplier < 0)
7558 af_period_multiplier = 2;
7559 else if (af_period_multiplier > 4)
7560 af_period_multiplier = 4;
7561
7562 ALOGV("new period_multiplier = %d", af_period_multiplier);
7563 }
7564
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007565 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007566 pthread_mutex_unlock(&adev_init_lock);
7567
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007568 if (adev->adm_init)
7569 adev->adm_data = adev->adm_init();
7570
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307571 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307572 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007573 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307574
7575 audio_extn_snd_mon_init();
7576 pthread_mutex_lock(&adev->lock);
7577 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
7578 adev->card_status = CARD_STATUS_ONLINE;
7579 pthread_mutex_unlock(&adev->lock);
7580 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307581 /* Allocate memory for Device config params */
7582 adev->device_cfg_params = (struct audio_device_config_param*)
7583 calloc(platform_get_max_codec_backend(),
7584 sizeof(struct audio_device_config_param));
7585 if (adev->device_cfg_params == NULL)
7586 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307587
Eric Laurent994a6932013-07-17 11:51:42 -07007588 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007589 return 0;
7590}
7591
7592static struct hw_module_methods_t hal_module_methods = {
7593 .open = adev_open,
7594};
7595
7596struct audio_module HAL_MODULE_INFO_SYM = {
7597 .common = {
7598 .tag = HARDWARE_MODULE_TAG,
7599 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
7600 .hal_api_version = HARDWARE_HAL_API_VERSION,
7601 .id = AUDIO_HARDWARE_MODULE_ID,
7602 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08007603 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007604 .methods = &hal_module_methods,
7605 },
7606};