blob: 7add4fdee0469dd390b503a424a3cdb8272c00d7 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05302 * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070066#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070068#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053077#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080080#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080081
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053082#ifdef DYNAMIC_LOG_ENABLED
83#include <log_xml_parser.h>
84#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
85#include <log_utils.h>
86#endif
87
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053089/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
90#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuriebe78a72018-10-04 18:23:46 -070092#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070093#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053094#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070095
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070096#define PROXY_OPEN_RETRY_COUNT 100
97#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080098
Mingming Yin08c7e312015-03-16 18:10:58 -070099#ifdef USE_LL_AS_PRIMARY_OUTPUT
100#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
101#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
102#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800103#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700104#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
105#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800106
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700107#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700108#define DEFAULT_VOIP_BUF_DURATION_MS 20
109#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
110#define DEFAULT_VOIP_SAMP_RATE 48000
111
112#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
113
114struct pcm_config default_pcm_config_voip_copp = {
115 .channels = 1,
116 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
117 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
118 .period_count = 2,
119 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800120 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
121 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700122};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700123
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700124#define MIN_CHANNEL_COUNT 1
125#define DEFAULT_CHANNEL_COUNT 2
126#define MAX_HIFI_CHANNEL_COUNT 8
127
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700128static unsigned int configured_low_latency_capture_period_size =
129 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
130
Haynes Mathew George16081042017-05-31 17:16:49 -0700131#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
132#define MMAP_PERIOD_COUNT_MIN 32
133#define MMAP_PERIOD_COUNT_MAX 512
134#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
135
Eric Laurentb23d5282013-05-14 15:27:20 -0700136struct pcm_config pcm_config_deep_buffer = {
137 .channels = 2,
138 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
139 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
140 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
141 .format = PCM_FORMAT_S16_LE,
142 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
143 .stop_threshold = INT_MAX,
144 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
145};
146
147struct pcm_config pcm_config_low_latency = {
148 .channels = 2,
149 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
150 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
151 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
152 .format = PCM_FORMAT_S16_LE,
153 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
154 .stop_threshold = INT_MAX,
155 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
156};
157
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700158static int af_period_multiplier = 4;
159struct pcm_config pcm_config_rt = {
160 .channels = 2,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = ULL_PERIOD_SIZE, //1 ms
163 .period_count = 512, //=> buffer size is 512ms
164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
166 .stop_threshold = INT_MAX,
167 .silence_threshold = 0,
168 .silence_size = 0,
169 .avail_min = ULL_PERIOD_SIZE, //1 ms
170};
171
Eric Laurentb23d5282013-05-14 15:27:20 -0700172struct pcm_config pcm_config_hdmi_multi = {
173 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
174 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
175 .period_size = HDMI_MULTI_PERIOD_SIZE,
176 .period_count = HDMI_MULTI_PERIOD_COUNT,
177 .format = PCM_FORMAT_S16_LE,
178 .start_threshold = 0,
179 .stop_threshold = INT_MAX,
180 .avail_min = 0,
181};
182
Haynes Mathew George16081042017-05-31 17:16:49 -0700183struct pcm_config pcm_config_mmap_playback = {
184 .channels = 2,
185 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
186 .period_size = MMAP_PERIOD_SIZE,
187 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
188 .format = PCM_FORMAT_S16_LE,
189 .start_threshold = MMAP_PERIOD_SIZE*8,
190 .stop_threshold = INT32_MAX,
191 .silence_threshold = 0,
192 .silence_size = 0,
193 .avail_min = MMAP_PERIOD_SIZE, //1 ms
194};
195
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700196struct pcm_config pcm_config_hifi = {
197 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
198 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
199 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
200 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
201 .format = PCM_FORMAT_S24_3LE,
202 .start_threshold = 0,
203 .stop_threshold = INT_MAX,
204 .avail_min = 0,
205};
206
Eric Laurentb23d5282013-05-14 15:27:20 -0700207struct pcm_config pcm_config_audio_capture = {
208 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700209 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
210 .format = PCM_FORMAT_S16_LE,
211};
212
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700213struct pcm_config pcm_config_audio_capture_rt = {
214 .channels = 2,
215 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
216 .period_size = ULL_PERIOD_SIZE,
217 .period_count = 512,
218 .format = PCM_FORMAT_S16_LE,
219 .start_threshold = 0,
220 .stop_threshold = INT_MAX,
221 .silence_threshold = 0,
222 .silence_size = 0,
223 .avail_min = ULL_PERIOD_SIZE, //1 ms
224};
225
Haynes Mathew George16081042017-05-31 17:16:49 -0700226struct pcm_config pcm_config_mmap_capture = {
227 .channels = 2,
228 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
229 .period_size = MMAP_PERIOD_SIZE,
230 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
231 .format = PCM_FORMAT_S16_LE,
232 .start_threshold = 0,
233 .stop_threshold = INT_MAX,
234 .silence_threshold = 0,
235 .silence_size = 0,
236 .avail_min = MMAP_PERIOD_SIZE, //1 ms
237};
238
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700239#define AFE_PROXY_CHANNEL_COUNT 2
240#define AFE_PROXY_SAMPLING_RATE 48000
241
242#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
243#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
244
245struct pcm_config pcm_config_afe_proxy_playback = {
246 .channels = AFE_PROXY_CHANNEL_COUNT,
247 .rate = AFE_PROXY_SAMPLING_RATE,
248 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
249 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
250 .format = PCM_FORMAT_S16_LE,
251 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
252 .stop_threshold = INT_MAX,
253 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
254};
255
256#define AFE_PROXY_RECORD_PERIOD_SIZE 768
257#define AFE_PROXY_RECORD_PERIOD_COUNT 4
258
259struct pcm_config pcm_config_afe_proxy_record = {
260 .channels = AFE_PROXY_CHANNEL_COUNT,
261 .rate = AFE_PROXY_SAMPLING_RATE,
262 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
263 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
264 .format = PCM_FORMAT_S16_LE,
265 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
266 .stop_threshold = INT_MAX,
267 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
268};
269
Ashish Jainf1eaa582016-05-23 20:54:24 +0530270#define AUDIO_MAX_PCM_FORMATS 7
271
272const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
273 [AUDIO_FORMAT_DEFAULT] = 0,
274 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
275 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
276 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
277 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
278 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
279 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
280};
281
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800282const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700283 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
284 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700285 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
286 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700287 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700288 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700289 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
290 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
291 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
292 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
293 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
294 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
295 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
296 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700297 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
298 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700299 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700300
Eric Laurentb23d5282013-05-14 15:27:20 -0700301 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700302 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530303 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
304 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
305 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530306 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
307 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700308 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700309 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700310 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700311 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700312
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800313 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800314 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700315 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700316
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700317 [USECASE_VOICE2_CALL] = "voice2-call",
318 [USECASE_VOLTE_CALL] = "volte-call",
319 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800320 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800321 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
322 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800323 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700324 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
325 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
326 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800327 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
328 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
329 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
330
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700331 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
332 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700333 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
334 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700335
336 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
337 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530338 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700339
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530340 /* Transcode loopback cases */
341 [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700342
343 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
344 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530345 /* For Interactive Audio Streams */
346 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
347 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
348 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
349 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
350 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
351 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
352 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
353 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700354
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800355 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
356
357 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback"
Eric Laurentb23d5282013-05-14 15:27:20 -0700358};
359
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700360static const audio_usecase_t offload_usecases[] = {
361 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700362 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
363 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
364 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
365 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
366 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
367 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
368 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
369 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700370};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800371
Varun Balaraje49253e2017-07-06 19:48:56 +0530372static const audio_usecase_t interactive_usecases[] = {
373 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
374 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
375 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
376 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
377 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
378 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
379 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
380 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
381};
382
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800383#define STRING_TO_ENUM(string) { #string, string }
384
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800385struct string_to_enum {
386 const char *name;
387 uint32_t value;
388};
389
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700390static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800391 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800392 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
393 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
394 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700395 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800396 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
397 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800398 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700399 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
400 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
401 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
402 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
403 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
404 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
405 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
406 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
407 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
408 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
409 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800410};
411
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700412static const struct string_to_enum formats_name_to_enum_table[] = {
413 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
414 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
415 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700416 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
417 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
418 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700419 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800420 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
421 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700422 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800423};
424
425//list of all supported sample rates by HDMI specification.
426static const int out_hdmi_sample_rates[] = {
427 32000, 44100, 48000, 88200, 96000, 176400, 192000,
428};
429
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700430static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800431 STRING_TO_ENUM(32000),
432 STRING_TO_ENUM(44100),
433 STRING_TO_ENUM(48000),
434 STRING_TO_ENUM(88200),
435 STRING_TO_ENUM(96000),
436 STRING_TO_ENUM(176400),
437 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700438};
439
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700440static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700441static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700442static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700443//cache last MBDRC cal step level
444static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700445
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530446static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
447static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuriebe78a72018-10-04 18:23:46 -0700448static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800449static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530450
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700451static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
452 int flags __unused)
453{
454 int dir = 0;
455 switch (uc_id) {
456 case USECASE_AUDIO_RECORD_LOW_LATENCY:
457 dir = 1;
458 case USECASE_AUDIO_PLAYBACK_ULL:
459 break;
460 default:
461 return false;
462 }
463
464 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
465 PCM_PLAYBACK : PCM_CAPTURE);
466 if (adev->adm_is_noirq_avail)
467 return adev->adm_is_noirq_avail(adev->adm_data,
468 adev->snd_card, dev_id, dir);
469 return false;
470}
471
472static void register_out_stream(struct stream_out *out)
473{
474 struct audio_device *adev = out->dev;
475 if (is_offload_usecase(out->usecase) ||
476 !adev->adm_register_output_stream)
477 return;
478
479 // register stream first for backward compatibility
480 adev->adm_register_output_stream(adev->adm_data,
481 out->handle,
482 out->flags);
483
484 if (!adev->adm_set_config)
485 return;
486
487 if (out->realtime)
488 adev->adm_set_config(adev->adm_data,
489 out->handle,
490 out->pcm, &out->config);
491}
492
493static void register_in_stream(struct stream_in *in)
494{
495 struct audio_device *adev = in->dev;
496 if (!adev->adm_register_input_stream)
497 return;
498
499 adev->adm_register_input_stream(adev->adm_data,
500 in->capture_handle,
501 in->flags);
502
503 if (!adev->adm_set_config)
504 return;
505
506 if (in->realtime)
507 adev->adm_set_config(adev->adm_data,
508 in->capture_handle,
509 in->pcm,
510 &in->config);
511}
512
513static void request_out_focus(struct stream_out *out, long ns)
514{
515 struct audio_device *adev = out->dev;
516
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700517 if (adev->adm_request_focus_v2)
518 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
519 else if (adev->adm_request_focus)
520 adev->adm_request_focus(adev->adm_data, out->handle);
521}
522
523static void request_in_focus(struct stream_in *in, long ns)
524{
525 struct audio_device *adev = in->dev;
526
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700527 if (adev->adm_request_focus_v2)
528 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
529 else if (adev->adm_request_focus)
530 adev->adm_request_focus(adev->adm_data, in->capture_handle);
531}
532
533static void release_out_focus(struct stream_out *out)
534{
535 struct audio_device *adev = out->dev;
536
537 if (adev->adm_abandon_focus)
538 adev->adm_abandon_focus(adev->adm_data, out->handle);
539}
540
541static void release_in_focus(struct stream_in *in)
542{
543 struct audio_device *adev = in->dev;
544 if (adev->adm_abandon_focus)
545 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
546}
547
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530548static int parse_snd_card_status(struct str_parms *parms, int *card,
549 card_status_t *status)
550{
551 char value[32]={0};
552 char state[32]={0};
553
554 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
555 if (ret < 0)
556 return -1;
557
558 // sscanf should be okay as value is of max length 32.
559 // same as sizeof state.
560 if (sscanf(value, "%d,%s", card, state) < 2)
561 return -1;
562
563 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
564 CARD_STATUS_OFFLINE;
565 return 0;
566}
567
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700568static inline void adjust_frames_for_device_delay(struct stream_out *out,
569 uint32_t *dsp_frames) {
570 // Adjustment accounts for A2dp encoder latency with offload usecases
571 // Note: Encoder latency is returned in ms.
572 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
573 unsigned long offset =
574 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
575 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
576 }
577}
578
vivek mehtaa76401a2015-04-24 14:12:15 -0700579__attribute__ ((visibility ("default")))
580bool audio_hw_send_gain_dep_calibration(int level) {
581 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700582 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700583
584 pthread_mutex_lock(&adev_init_lock);
585
586 if (adev != NULL && adev->platform != NULL) {
587 pthread_mutex_lock(&adev->lock);
588 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700589
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530590 // cache level info for any of the use case which
591 // was not started.
592 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700593
vivek mehtaa76401a2015-04-24 14:12:15 -0700594 pthread_mutex_unlock(&adev->lock);
595 } else {
596 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
597 }
598
599 pthread_mutex_unlock(&adev_init_lock);
600
601 return ret_val;
602}
603
Ashish Jain5106d362016-05-11 19:23:33 +0530604static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
605{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800606 bool gapless_enabled = false;
607 const char *mixer_ctl_name = "Compress Gapless Playback";
608 struct mixer_ctl *ctl;
609
610 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700611 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530612
613 /*Disable gapless if its AV playback*/
614 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800615
616 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
617 if (!ctl) {
618 ALOGE("%s: Could not get ctl for mixer cmd - %s",
619 __func__, mixer_ctl_name);
620 return -EINVAL;
621 }
622
623 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
624 ALOGE("%s: Could not set gapless mode %d",
625 __func__, gapless_enabled);
626 return -EINVAL;
627 }
628 return 0;
629}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700630
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700631__attribute__ ((visibility ("default")))
632int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
633 int table_size) {
634 int ret_val = 0;
635 ALOGV("%s: enter ... ", __func__);
636
637 pthread_mutex_lock(&adev_init_lock);
638 if (adev == NULL) {
639 ALOGW("%s: adev is NULL .... ", __func__);
640 goto done;
641 }
642
643 pthread_mutex_lock(&adev->lock);
644 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
645 pthread_mutex_unlock(&adev->lock);
646done:
647 pthread_mutex_unlock(&adev_init_lock);
648 ALOGV("%s: exit ... ", __func__);
649 return ret_val;
650}
651
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700652static bool is_supported_format(audio_format_t format)
653{
Eric Laurent86e17132013-09-12 17:49:30 -0700654 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530655 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530656 format == AUDIO_FORMAT_AAC_LC ||
657 format == AUDIO_FORMAT_AAC_HE_V1 ||
658 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530659 format == AUDIO_FORMAT_AAC_ADTS_LC ||
660 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
661 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530662 format == AUDIO_FORMAT_AAC_LATM_LC ||
663 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
664 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530665 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
666 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530667 format == AUDIO_FORMAT_PCM_FLOAT ||
668 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700669 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530670 format == AUDIO_FORMAT_AC3 ||
671 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700672 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530673 format == AUDIO_FORMAT_DTS ||
674 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800675 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530676 format == AUDIO_FORMAT_ALAC ||
677 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530678 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530679 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800680 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530681 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700682 format == AUDIO_FORMAT_APTX ||
683 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800684 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700685
686 return false;
687}
688
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700689static inline bool is_mmap_usecase(audio_usecase_t uc_id)
690{
691 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
692 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
693}
694
Avinash Vaish71a8b972014-07-24 15:36:33 +0530695static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
696 struct audio_usecase *uc_info)
697{
698 struct listnode *node;
699 struct audio_usecase *usecase;
700
701 if (uc_info == NULL)
702 return -EINVAL;
703
704 /* Re-route all voice usecases on the shared backend other than the
705 specified usecase to new snd devices */
706 list_for_each(node, &adev->usecase_list) {
707 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800708 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530709 enable_audio_route(adev, usecase);
710 }
711 return 0;
712}
713
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530714static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530715{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530716 ALOGV("%s", __func__);
717 audio_route_apply_and_update_path(adev->audio_route,
718 "asrc-mode");
719 adev->asrc_mode_enabled = true;
720}
721
722static void disable_asrc_mode(struct audio_device *adev)
723{
724 ALOGV("%s", __func__);
725 audio_route_reset_and_update_path(adev->audio_route,
726 "asrc-mode");
727 adev->asrc_mode_enabled = false;
728}
729
730/*
731 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
732 * 44.1 or Native DSD backends are enabled for any of current use case.
733 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
734 * - Disable current mix path use case(Headphone backend) and re-enable it with
735 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
736 * e.g. Naitve DSD or Headphone 44.1 -> + 48
737 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530738static void check_and_set_asrc_mode(struct audio_device *adev,
739 struct audio_usecase *uc_info,
740 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530741{
742 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530743 int i, num_new_devices = 0;
744 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
745 /*
746 *Split snd device for new combo use case
747 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
748 */
749 if (platform_split_snd_device(adev->platform,
750 snd_device,
751 &num_new_devices,
752 split_new_snd_devices) == 0) {
753 for (i = 0; i < num_new_devices; i++)
754 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
755 } else {
756 int new_backend_idx = platform_get_backend_index(snd_device);
757 if (((new_backend_idx == HEADPHONE_BACKEND) ||
758 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
759 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
760 !adev->asrc_mode_enabled) {
761 struct listnode *node = NULL;
762 struct audio_usecase *uc = NULL;
763 struct stream_out *curr_out = NULL;
764 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
765 int i, num_devices, ret = 0;
766 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530767
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530768 list_for_each(node, &adev->usecase_list) {
769 uc = node_to_item(node, struct audio_usecase, list);
770 curr_out = (struct stream_out*) uc->stream.out;
771 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
772 /*
773 *Split snd device for existing combo use case
774 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
775 */
776 ret = platform_split_snd_device(adev->platform,
777 uc->out_snd_device,
778 &num_devices,
779 split_snd_devices);
780 if (ret < 0 || num_devices == 0) {
781 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
782 split_snd_devices[0] = uc->out_snd_device;
783 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800784 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530785 for (i = 0; i < num_devices; i++) {
786 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
787 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
788 if((new_backend_idx == HEADPHONE_BACKEND) &&
789 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
790 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
791 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
792 __func__);
793 enable_asrc_mode(adev);
794 break;
795 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
796 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
797 (usecase_backend_idx == HEADPHONE_BACKEND)) {
798 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
799 __func__);
800 disable_audio_route(adev, uc);
801 disable_snd_device(adev, uc->out_snd_device);
802 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
803 if (new_backend_idx == DSD_NATIVE_BACKEND)
804 audio_route_apply_and_update_path(adev->audio_route,
805 "hph-true-highquality-mode");
806 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
807 (curr_out->bit_width >= 24))
808 audio_route_apply_and_update_path(adev->audio_route,
809 "hph-highquality-mode");
810 enable_asrc_mode(adev);
811 enable_snd_device(adev, uc->out_snd_device);
812 enable_audio_route(adev, uc);
813 break;
814 }
815 }
816 // reset split devices count
817 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800818 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530819 if (adev->asrc_mode_enabled)
820 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530821 }
822 }
823 }
824}
825
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700826#ifdef DYNAMIC_ECNS_ENABLED
827static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
828 struct audio_effect_config effect_config,
829 unsigned int param_value)
830{
831 char mixer_ctl_name[] = "Audio Effect";
832 struct mixer_ctl *ctl;
833 long set_values[6];
834 struct stream_in *in = adev->active_input;
835
836 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
837 if (!ctl) {
838 ALOGE("%s: Could not get mixer ctl - %s",
839 __func__, mixer_ctl_name);
840 return -EINVAL;
841 }
842
843 set_values[0] = 1; //0:Rx 1:Tx
844 set_values[1] = in->app_type_cfg.app_type;
845 set_values[2] = (long)effect_config.module_id;
846 set_values[3] = (long)effect_config.instance_id;
847 set_values[4] = (long)effect_config.param_id;
848 set_values[5] = param_value;
849
850 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
851
852 return 0;
853
854}
855
856static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
857 int effect_type, unsigned int *param_value)
858{
859 int ret = 0;
860 struct audio_effect_config other_effect_config;
861 struct audio_usecase *usecase = NULL;
862 struct stream_in *in = adev->active_input;
863
864 usecase = get_usecase_from_list(adev, in->usecase);
865 if (!usecase)
866 return -EINVAL;
867
868 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
869 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
870 if (ret < 0) {
871 ALOGE("%s Failed to get effect params %d", __func__, ret);
872 return ret;
873 }
874
875 if (module_id == other_effect_config.module_id) {
876 //Same module id for AEC/NS. Values need to be combined
877 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
878 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
879 *param_value |= other_effect_config.param_value;
880 }
881 }
882
883 return ret;
884}
885
886static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
887{
888 struct audio_effect_config effect_config;
889 struct audio_usecase *usecase = NULL;
890 int ret = 0;
891 unsigned int param_value = 0;
892 struct stream_in *in = adev->active_input;
893
894 if (!in) {
895 ALOGE("%s: Invalid input stream", __func__);
896 return -EINVAL;
897 }
898
899 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
900
901 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800902 if (usecase == NULL) {
903 ALOGE("%s: Could not find the usecase (%d) in the list",
904 __func__, in->usecase);
905 return -EINVAL;
906 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700907
908 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
909 if (ret < 0) {
910 ALOGE("%s Failed to get module id %d", __func__, ret);
911 return ret;
912 }
913 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
914 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
915
916 if(enable)
917 param_value = effect_config.param_value;
918
919 /*Special handling for AEC & NS effects Param values need to be
920 updated if module ids are same*/
921
922 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
923 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
924 if (ret < 0)
925 return ret;
926 }
927
928 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
929
930 return ret;
931}
932
933static void check_and_enable_effect(struct audio_device *adev)
934{
935
936 if (adev->active_input->enable_aec) {
937 enable_disable_effect(adev, EFFECT_AEC, true);
938 }
939
940 if (adev->active_input->enable_ns &&
941 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
942 enable_disable_effect(adev, EFFECT_NS, true);
943 }
944}
945#else
946#define enable_disable_effect(x, y, z) ENOSYS
947#define check_and_enable_effect(x) ENOSYS
948#endif
949
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700950int pcm_ioctl(struct pcm *pcm, int request, ...)
951{
952 va_list ap;
953 void * arg;
954 int pcm_fd = *(int*)pcm;
955
956 va_start(ap, request);
957 arg = va_arg(ap, void *);
958 va_end(ap);
959
960 return ioctl(pcm_fd, request, arg);
961}
962
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700963int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700964 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800965{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700966 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700967 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530968 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800969
970 if (usecase == NULL)
971 return -EINVAL;
972
973 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
974
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800975 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700976 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800977 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700978 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800979
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800980#ifdef DS1_DOLBY_DAP_ENABLED
981 audio_extn_dolby_set_dmid(adev);
982 audio_extn_dolby_set_endpoint(adev);
983#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700984 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700985 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530986 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700987 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530988 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530989 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
990 out = usecase->stream.out;
991 if (out && out->compr)
992 audio_extn_utils_compress_set_clk_rec_mode(usecase);
993 }
994
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800995 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700996 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700997 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700998 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800999 ALOGV("%s: exit", __func__);
1000 return 0;
1001}
1002
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001003int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001004 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001005{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001006 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001007 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001008
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301009 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001010 return -EINVAL;
1011
1012 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001013 if (usecase->type == PCM_CAPTURE)
1014 snd_device = usecase->in_snd_device;
1015 else
1016 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001017 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001018 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001019 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001020 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001021 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301022 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001023 ALOGV("%s: exit", __func__);
1024 return 0;
1025}
1026
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001027int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001028 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001029{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301030 int i, num_devices = 0;
1031 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001032 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1033
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001034 if (snd_device < SND_DEVICE_MIN ||
1035 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001036 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001037 return -EINVAL;
1038 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001039
1040 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001041
1042 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
1043 ALOGE("%s: Invalid sound device returned", __func__);
1044 return -EINVAL;
1045 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001046 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -07001047 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001048 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049 return 0;
1050 }
1051
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301052
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001053 if (audio_extn_spkr_prot_is_enabled())
1054 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001055
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001056 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1057 audio_extn_spkr_prot_is_enabled()) {
1058 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001059 adev->snd_dev_ref_cnt[snd_device]--;
1060 return -EINVAL;
1061 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001062 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001063 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001064 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001065 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001066 return -EINVAL;
1067 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001068 } else if (platform_split_snd_device(adev->platform,
1069 snd_device,
1070 &num_devices,
1071 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301072 for (i = 0; i < num_devices; i++) {
1073 enable_snd_device(adev, new_snd_devices[i]);
1074 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001075 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001076 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301077
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301078
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301079 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1080 (audio_extn_a2dp_start_playback() < 0)) {
1081 ALOGE(" fail to configure A2dp control path ");
1082 return -EINVAL;
1083 }
1084
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001085 /* due to the possibility of calibration overwrite between listen
1086 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001087 audio_extn_sound_trigger_update_device_status(snd_device,
1088 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301089 audio_extn_listen_update_device_status(snd_device,
1090 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001091 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001092 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001093 audio_extn_sound_trigger_update_device_status(snd_device,
1094 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301095 audio_extn_listen_update_device_status(snd_device,
1096 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001097 return -EINVAL;
1098 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001099 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001100 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301101
1102 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1103 !adev->native_playback_enabled &&
1104 audio_is_true_native_stream_active(adev)) {
1105 ALOGD("%s: %d: napb: enabling native mode in hardware",
1106 __func__, __LINE__);
1107 audio_route_apply_and_update_path(adev->audio_route,
1108 "true-native-mode");
1109 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301110 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001111 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1112 (audio_extn_ffv_get_stream() == adev->active_input)) {
1113 ALOGD("%s: init ec ref loopback", __func__);
1114 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1115 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001116 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117 return 0;
1118}
1119
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001120int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001121 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001122{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301123 int i, num_devices = 0;
1124 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001125 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1126
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001127 if (snd_device < SND_DEVICE_MIN ||
1128 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001129 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001130 return -EINVAL;
1131 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001132 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1133 ALOGE("%s: device ref cnt is already 0", __func__);
1134 return -EINVAL;
1135 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001136
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001138
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001139 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1140 ALOGE("%s: Invalid sound device returned", __func__);
1141 return -EINVAL;
1142 }
1143
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001144 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001145 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301146
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001147 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1148 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001149 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001150
1151 // when speaker device is disabled, reset swap.
1152 // will be renabled on usecase start
1153 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001154 } else if (platform_split_snd_device(adev->platform,
1155 snd_device,
1156 &num_devices,
1157 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301158 for (i = 0; i < num_devices; i++) {
1159 disable_snd_device(adev, new_snd_devices[i]);
1160 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001161 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001162 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001163 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001164
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301165 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1166 audio_extn_a2dp_stop_playback();
1167
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001168 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301169 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301170 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1171 adev->native_playback_enabled) {
1172 ALOGD("%s: %d: napb: disabling native mode in hardware",
1173 __func__, __LINE__);
1174 audio_route_reset_and_update_path(adev->audio_route,
1175 "true-native-mode");
1176 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301177 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1178 adev->asrc_mode_enabled) {
1179 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301180 disable_asrc_mode(adev);
1181 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301182 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001183 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1184 (audio_extn_ffv_get_stream() == adev->active_input)) {
1185 ALOGD("%s: deinit ec ref loopback", __func__);
1186 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1187 }
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001188 audio_extn_utils_release_snd_device(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001189 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001191 return 0;
1192}
1193
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001194/*
1195 legend:
1196 uc - existing usecase
1197 new_uc - new usecase
1198 d1, d11, d2 - SND_DEVICE enums
1199 a1, a2 - corresponding ANDROID device enums
1200 B1, B2 - backend strings
1201
1202case 1
1203 uc->dev d1 (a1) B1
1204 new_uc->dev d1 (a1), d2 (a2) B1, B2
1205
1206 resolution: disable and enable uc->dev on d1
1207
1208case 2
1209 uc->dev d1 (a1) B1
1210 new_uc->dev d11 (a1) B1
1211
1212 resolution: need to switch uc since d1 and d11 are related
1213 (e.g. speaker and voice-speaker)
1214 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1215
1216case 3
1217 uc->dev d1 (a1) B1
1218 new_uc->dev d2 (a2) B2
1219
1220 resolution: no need to switch uc
1221
1222case 4
1223 uc->dev d1 (a1) B1
1224 new_uc->dev d2 (a2) B1
1225
1226 resolution: disable enable uc-dev on d2 since backends match
1227 we cannot enable two streams on two different devices if they
1228 share the same backend. e.g. if offload is on speaker device using
1229 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1230 using the same backend, offload must also be switched to voice-handset.
1231
1232case 5
1233 uc->dev d1 (a1) B1
1234 new_uc->dev d1 (a1), d2 (a2) B1
1235
1236 resolution: disable enable uc-dev on d2 since backends match
1237 we cannot enable two streams on two different devices if they
1238 share the same backend.
1239
1240case 6
1241 uc->dev d1 (a1) B1
1242 new_uc->dev d2 (a1) B2
1243
1244 resolution: no need to switch
1245
1246case 7
1247 uc->dev d1 (a1), d2 (a2) B1, B2
1248 new_uc->dev d1 (a1) B1
1249
1250 resolution: no need to switch
1251
Zhou Song4ba65882018-07-09 14:48:07 +08001252case 8
1253 uc->dev d1 (a1) B1
1254 new_uc->dev d11 (a1), d2 (a2) B1, B2
1255 resolution: compared to case 1, for this case, d1 and d11 are related
1256 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001257*/
1258static snd_device_t derive_playback_snd_device(void * platform,
1259 struct audio_usecase *uc,
1260 struct audio_usecase *new_uc,
1261 snd_device_t new_snd_device)
1262{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301263 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001264
1265 snd_device_t d1 = uc->out_snd_device;
1266 snd_device_t d2 = new_snd_device;
1267
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301268 switch (uc->type) {
1269 case TRANSCODE_LOOPBACK :
1270 a1 = uc->stream.inout->out_config.devices;
1271 a2 = new_uc->stream.inout->out_config.devices;
1272 break;
1273 default :
1274 a1 = uc->stream.out->devices;
1275 a2 = new_uc->stream.out->devices;
1276 break;
1277 }
1278
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001279 // Treat as a special case when a1 and a2 are not disjoint
1280 if ((a1 != a2) && (a1 & a2)) {
1281 snd_device_t d3[2];
1282 int num_devices = 0;
1283 int ret = platform_split_snd_device(platform,
1284 popcount(a1) > 1 ? d1 : d2,
1285 &num_devices,
1286 d3);
1287 if (ret < 0) {
1288 if (ret != -ENOSYS) {
1289 ALOGW("%s failed to split snd_device %d",
1290 __func__,
1291 popcount(a1) > 1 ? d1 : d2);
1292 }
1293 goto end;
1294 }
1295
1296 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1297 // But if it does happen, we need to give priority to d2 if
1298 // the combo devices active on the existing usecase share a backend.
1299 // This is because we cannot have a usecase active on a combo device
1300 // and a new usecase requests one device in this combo pair.
1301 if (platform_check_backends_match(d3[0], d3[1])) {
1302 return d2; // case 5
1303 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001304 // check if d1 is related to any of d3's
1305 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001306 return d1; // case 1
1307 else
1308 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001309 }
1310 } else {
1311 if (platform_check_backends_match(d1, d2)) {
1312 return d2; // case 2, 4
1313 } else {
1314 return d1; // case 6, 3
1315 }
1316 }
1317
1318end:
1319 return d2; // return whatever was calculated before.
1320}
1321
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001322static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301323 struct audio_usecase *uc_info,
1324 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001325{
1326 struct listnode *node;
1327 struct audio_usecase *usecase;
1328 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301329 snd_device_t uc_derive_snd_device;
1330 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001331 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1332 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001333 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301334 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001335 /*
1336 * This function is to make sure that all the usecases that are active on
1337 * the hardware codec backend are always routed to any one device that is
1338 * handled by the hardware codec.
1339 * For example, if low-latency and deep-buffer usecases are currently active
1340 * on speaker and out_set_parameters(headset) is received on low-latency
1341 * output, then we have to make sure deep-buffer is also switched to headset,
1342 * because of the limitation that both the devices cannot be enabled
1343 * at the same time as they share the same backend.
1344 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001345 /*
1346 * This call is to check if we need to force routing for a particular stream
1347 * If there is a backend configuration change for the device when a
1348 * new stream starts, then ADM needs to be closed and re-opened with the new
1349 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001350 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001351 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001352 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1353 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301354 /* For a2dp device reconfigure all active sessions
1355 * with new AFE encoder format based on a2dp state
1356 */
1357 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1358 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1359 audio_extn_a2dp_is_force_device_switch()) {
1360 force_routing = true;
1361 force_restart_session = true;
1362 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301363 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1364
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001365 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001366 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001367 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001368 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1369 switch_device[i] = false;
1370
1371 list_for_each(node, &adev->usecase_list) {
1372 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001373
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301374 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1375 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301376 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301377 platform_get_snd_device_name(usecase->out_snd_device),
1378 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301379 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1380 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1381 usecase, uc_info, snd_device);
1382 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1383 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1384 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1385 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001386 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301387 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1388 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1389 ((force_restart_session) ||
1390 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301391 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1392 __func__, use_case_table[usecase->id],
1393 platform_get_snd_device_name(usecase->out_snd_device));
1394 disable_audio_route(adev, usecase);
1395 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301396 /* Enable existing usecase on derived playback device */
1397 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301398 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301399 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001400 }
1401 }
1402
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301403 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1404 num_uc_to_switch);
1405
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001406 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001407 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001408
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301409 /* Make sure the previous devices to be disabled first and then enable the
1410 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001411 list_for_each(node, &adev->usecase_list) {
1412 usecase = node_to_item(node, struct audio_usecase, list);
1413 if (switch_device[usecase->id]) {
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001414 /* Check if output sound device to be switched can be split and if any
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001415 of the split devices match with derived sound device */
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001416 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1417 &num_devices, split_snd_devices) == 0) {
1418 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1419 if (adev->snd_dev_ref_cnt[usecase->out_snd_device] == 0) {
1420 ALOGD("%s: disabling snd_device(%d)", __func__, usecase->out_snd_device);
1421 for (i = 0; i < num_devices; i++) {
1422 /* Disable devices that do not match with derived sound device */
1423 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1424 disable_snd_device(adev, split_snd_devices[i]);
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001425 }
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001426 audio_extn_utils_release_snd_device(usecase->out_snd_device);
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001427 }
1428 } else {
1429 disable_snd_device(adev, usecase->out_snd_device);
1430 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001431 }
1432 }
1433
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001434 list_for_each(node, &adev->usecase_list) {
1435 usecase = node_to_item(node, struct audio_usecase, list);
1436 if (switch_device[usecase->id]) {
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001437 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1438 &num_devices, split_snd_devices) == 0) {
1439 /* Enable derived sound device only if it does not match with
1440 one of the split sound devices. This is because the matching
1441 sound device was not disabled */
1442 bool should_enable = true;
1443 for (i = 0; i < num_devices; i++) {
1444 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1445 should_enable = false;
1446 break;
1447 }
1448 }
1449 if (should_enable)
1450 enable_snd_device(adev, derive_snd_device[usecase->id]);
1451 } else {
1452 enable_snd_device(adev, derive_snd_device[usecase->id]);
1453 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001454 }
1455 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001456
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001457 /* Re-route all the usecases on the shared backend other than the
1458 specified usecase to new snd devices */
1459 list_for_each(node, &adev->usecase_list) {
1460 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301461 /* Update the out_snd_device only before enabling the audio route */
1462 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301463 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301464 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301465 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301466 use_case_table[usecase->id],
1467 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001468 /* Update voc calibration before enabling VoIP route */
1469 if (usecase->type == VOIP_CALL)
1470 status = platform_switch_voice_call_device_post(adev->platform,
1471 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001472 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301473 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001474 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1475 out_set_voip_volume(&usecase->stream.out->stream,
1476 usecase->stream.out->volume_l,
1477 usecase->stream.out->volume_r);
1478 }
Yidong Huang7939a3b2018-01-23 17:32:30 +08001479 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1480 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1481 if (parms)
1482 audio_extn_fm_set_parameters(adev, parms);
1483 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301484 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001485 }
1486 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001487 }
1488}
1489
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301490static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001491 struct audio_usecase *uc_info,
1492 snd_device_t snd_device)
1493{
1494 struct listnode *node;
1495 struct audio_usecase *usecase;
1496 bool switch_device[AUDIO_USECASE_MAX];
1497 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301498 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001499 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001500
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301501 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1502 snd_device);
1503 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301504
1505 /*
1506 * Make sure out devices is checked against out codec backend device and
1507 * also in devices against in codec backend. Checking out device against in
1508 * codec backend or vice versa causes issues.
1509 */
1510 if (uc_info->type == PCM_CAPTURE)
1511 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001512 /*
1513 * This function is to make sure that all the active capture usecases
1514 * are always routed to the same input sound device.
1515 * For example, if audio-record and voice-call usecases are currently
1516 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1517 * is received for voice call then we have to make sure that audio-record
1518 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1519 * because of the limitation that two devices cannot be enabled
1520 * at the same time if they share the same backend.
1521 */
1522 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1523 switch_device[i] = false;
1524
1525 list_for_each(node, &adev->usecase_list) {
1526 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301527 /*
1528 * TODO: Enhance below condition to handle BT sco/USB multi recording
1529 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001530 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001531 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301532 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301533 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301534 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301535 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001536 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001537 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1538 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001539 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001540 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001541 switch_device[usecase->id] = true;
1542 num_uc_to_switch++;
1543 }
1544 }
1545
1546 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001547 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001548
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301549 /* Make sure the previous devices to be disabled first and then enable the
1550 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001551 list_for_each(node, &adev->usecase_list) {
1552 usecase = node_to_item(node, struct audio_usecase, list);
1553 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001554 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001555 }
1556 }
1557
1558 list_for_each(node, &adev->usecase_list) {
1559 usecase = node_to_item(node, struct audio_usecase, list);
1560 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001561 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001562 }
1563 }
1564
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001565 /* Re-route all the usecases on the shared backend other than the
1566 specified usecase to new snd devices */
1567 list_for_each(node, &adev->usecase_list) {
1568 usecase = node_to_item(node, struct audio_usecase, list);
1569 /* Update the in_snd_device only before enabling the audio route */
1570 if (switch_device[usecase->id] ) {
1571 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001572 if (usecase->type != VOICE_CALL) {
1573 /* Update voc calibration before enabling VoIP route */
1574 if (usecase->type == VOIP_CALL)
1575 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001576 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001577 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301578 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001579 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001580 }
1581 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001582 }
1583}
1584
Mingming Yin3a941d42016-02-17 18:08:05 -08001585static void reset_hdmi_sink_caps(struct stream_out *out) {
1586 int i = 0;
1587
1588 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1589 out->supported_channel_masks[i] = 0;
1590 }
1591 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1592 out->supported_formats[i] = 0;
1593 }
1594 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1595 out->supported_sample_rates[i] = 0;
1596 }
1597}
1598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001599/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001600static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001601{
Mingming Yin3a941d42016-02-17 18:08:05 -08001602 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001603 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001604
Mingming Yin3a941d42016-02-17 18:08:05 -08001605 reset_hdmi_sink_caps(out);
1606
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001607 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001608 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001609 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001610 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001611 }
1612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001613 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001614 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001615 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001616 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001617 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1618 case 6:
1619 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1620 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1621 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1622 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1623 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1624 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001625 break;
1626 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001627 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001628 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001629 break;
1630 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001631
1632 // check channel format caps
1633 i = 0;
1634 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1635 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1636 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1637 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1638 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1639 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1640 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1641 }
1642
Ben Romberger1aaaf862017-04-06 17:49:46 -07001643 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1644 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1645 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1646 }
1647
Mingming Yin3a941d42016-02-17 18:08:05 -08001648 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1649 ALOGV(":%s HDMI supports DTS format", __func__);
1650 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1651 }
1652
1653 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1654 ALOGV(":%s HDMI supports DTS HD format", __func__);
1655 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1656 }
1657
Naresh Tanniru928f0862017-04-07 16:44:23 -07001658 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1659 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1660 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1661 }
1662
Mingming Yin3a941d42016-02-17 18:08:05 -08001663
1664 // check sample rate caps
1665 i = 0;
1666 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1667 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1668 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1669 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1670 }
1671 }
1672
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001673 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674}
1675
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001676static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1677 uint32_t *supported_sample_rates __unused,
1678 uint32_t max_rates __unused)
1679{
1680 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1681 supported_sample_rates,
1682 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301683 ssize_t i = 0;
1684
1685 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001686 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1687 supported_sample_rates[i]);
1688 }
1689 return count;
1690}
1691
1692static inline int read_usb_sup_channel_masks(bool is_playback,
1693 audio_channel_mask_t *supported_channel_masks,
1694 uint32_t max_masks)
1695{
1696 int channels = audio_extn_usb_get_max_channels(is_playback);
1697 int channel_count;
1698 uint32_t num_masks = 0;
1699 if (channels > MAX_HIFI_CHANNEL_COUNT)
1700 channels = MAX_HIFI_CHANNEL_COUNT;
1701
1702 if (is_playback) {
1703 // For playback we never report mono because the framework always outputs stereo
1704 channel_count = DEFAULT_CHANNEL_COUNT;
1705 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1706 // above 2 but we want indexed masks here. So we
1707 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1708 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1709 }
1710 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1711 supported_channel_masks[num_masks++] =
1712 audio_channel_mask_for_index_assignment_from_count(channel_count);
1713 }
1714 } else {
1715 // For capture we report all supported channel masks from 1 channel up.
1716 channel_count = MIN_CHANNEL_COUNT;
1717 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1718 // indexed mask
1719 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1720 supported_channel_masks[num_masks++] =
1721 audio_channel_in_mask_from_count(channel_count);
1722 }
1723 }
1724 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1725 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1726 return num_masks;
1727}
1728
1729static inline int read_usb_sup_formats(bool is_playback __unused,
1730 audio_format_t *supported_formats,
1731 uint32_t max_formats __unused)
1732{
1733 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1734 switch (bitwidth) {
1735 case 24:
1736 // XXX : usb.c returns 24 for s24 and s24_le?
1737 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1738 break;
1739 case 32:
1740 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1741 break;
1742 case 16:
1743 default :
1744 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1745 break;
1746 }
1747 ALOGV("%s: %s supported format %d", __func__,
1748 is_playback ? "P" : "C", bitwidth);
1749 return 1;
1750}
1751
1752static inline int read_usb_sup_params_and_compare(bool is_playback,
1753 audio_format_t *format,
1754 audio_format_t *supported_formats,
1755 uint32_t max_formats,
1756 audio_channel_mask_t *mask,
1757 audio_channel_mask_t *supported_channel_masks,
1758 uint32_t max_masks,
1759 uint32_t *rate,
1760 uint32_t *supported_sample_rates,
1761 uint32_t max_rates) {
1762 int ret = 0;
1763 int num_formats;
1764 int num_masks;
1765 int num_rates;
1766 int i;
1767
1768 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1769 max_formats);
1770 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1771 max_masks);
1772
1773 num_rates = read_usb_sup_sample_rates(is_playback,
1774 supported_sample_rates, max_rates);
1775
1776#define LUT(table, len, what, dflt) \
1777 for (i=0; i<len && (table[i] != what); i++); \
1778 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1779
1780 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1781 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1782 LUT(supported_sample_rates, num_rates, *rate, 0);
1783
1784#undef LUT
1785 return ret < 0 ? -EINVAL : 0; // HACK TBD
1786}
1787
Alexy Josephb1379942016-01-29 15:49:38 -08001788audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001789 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001790{
1791 struct audio_usecase *usecase;
1792 struct listnode *node;
1793
1794 list_for_each(node, &adev->usecase_list) {
1795 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001796 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001797 ALOGV("%s: usecase id %d", __func__, usecase->id);
1798 return usecase->id;
1799 }
1800 }
1801 return USECASE_INVALID;
1802}
1803
Alexy Josephb1379942016-01-29 15:49:38 -08001804struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001805 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001806{
1807 struct audio_usecase *usecase;
1808 struct listnode *node;
1809
1810 list_for_each(node, &adev->usecase_list) {
1811 usecase = node_to_item(node, struct audio_usecase, list);
1812 if (usecase->id == uc_id)
1813 return usecase;
1814 }
1815 return NULL;
1816}
1817
Dhananjay Kumard4833242016-10-06 22:09:12 +05301818struct stream_in *get_next_active_input(const struct audio_device *adev)
1819{
1820 struct audio_usecase *usecase;
1821 struct listnode *node;
1822
1823 list_for_each_reverse(node, &adev->usecase_list) {
1824 usecase = node_to_item(node, struct audio_usecase, list);
1825 if (usecase->type == PCM_CAPTURE)
1826 return usecase->stream.in;
1827 }
1828 return NULL;
1829}
1830
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301831/*
1832 * is a true native playback active
1833 */
1834bool audio_is_true_native_stream_active(struct audio_device *adev)
1835{
1836 bool active = false;
1837 int i = 0;
1838 struct listnode *node;
1839
1840 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1841 ALOGV("%s:napb: not in true mode or non hdphones device",
1842 __func__);
1843 active = false;
1844 goto exit;
1845 }
1846
1847 list_for_each(node, &adev->usecase_list) {
1848 struct audio_usecase *uc;
1849 uc = node_to_item(node, struct audio_usecase, list);
1850 struct stream_out *curr_out =
1851 (struct stream_out*) uc->stream.out;
1852
1853 if (curr_out && PCM_PLAYBACK == uc->type) {
1854 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1855 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1856 uc->id, curr_out->sample_rate,
1857 curr_out->bit_width,
1858 platform_get_snd_device_name(uc->out_snd_device));
1859
1860 if (is_offload_usecase(uc->id) &&
1861 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1862 active = true;
1863 ALOGD("%s:napb:native stream detected", __func__);
1864 }
1865 }
1866 }
1867exit:
1868 return active;
1869}
1870
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001871uint32_t adev_get_dsp_bit_width_enforce_mode()
1872{
1873 if (adev == NULL) {
1874 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1875 return 0;
1876 }
1877 return adev->dsp_bit_width_enforce_mode;
1878}
1879
1880static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1881{
1882 char value[PROPERTY_VALUE_MAX];
1883 int trial;
1884 uint32_t dsp_bit_width_enforce_mode = 0;
1885
1886 if (!mixer) {
1887 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1888 __func__);
1889 return 0;
1890 }
1891
1892 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1893 value, NULL) > 0) {
1894 trial = atoi(value);
1895 switch (trial) {
1896 case 16:
1897 dsp_bit_width_enforce_mode = 16;
1898 break;
1899 case 24:
1900 dsp_bit_width_enforce_mode = 24;
1901 break;
1902 case 32:
1903 dsp_bit_width_enforce_mode = 32;
1904 break;
1905 default:
1906 dsp_bit_width_enforce_mode = 0;
1907 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1908 break;
1909 }
1910 }
1911
1912 return dsp_bit_width_enforce_mode;
1913}
1914
1915static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1916 uint32_t enforce_mode,
1917 bool enable)
1918{
1919 struct mixer_ctl *ctl = NULL;
1920 const char *mixer_ctl_name = "ASM Bit Width";
1921 uint32_t asm_bit_width_mode = 0;
1922
1923 if (enforce_mode == 0) {
1924 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1925 return;
1926 }
1927
1928 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1929 if (!ctl) {
1930 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1931 __func__, mixer_ctl_name);
1932 return;
1933 }
1934
1935 if (enable)
1936 asm_bit_width_mode = enforce_mode;
1937 else
1938 asm_bit_width_mode = 0;
1939
1940 ALOGV("%s DSP bit width feature status is %d width=%d",
1941 __func__, enable, asm_bit_width_mode);
1942 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1943 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1944 asm_bit_width_mode);
1945
1946 return;
1947}
1948
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301949/*
1950 * if native DSD playback active
1951 */
1952bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1953{
1954 bool active = false;
1955 struct listnode *node = NULL;
1956 struct audio_usecase *uc = NULL;
1957 struct stream_out *curr_out = NULL;
1958
1959 list_for_each(node, &adev->usecase_list) {
1960 uc = node_to_item(node, struct audio_usecase, list);
1961 curr_out = (struct stream_out*) uc->stream.out;
1962
1963 if (curr_out && PCM_PLAYBACK == uc->type &&
1964 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1965 active = true;
1966 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301967 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301968 }
1969 }
1970 return active;
1971}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301972
1973static bool force_device_switch(struct audio_usecase *usecase)
1974{
1975 bool ret = false;
1976 bool is_it_true_mode = false;
1977
Zhou Song30f2c3e2018-02-08 14:02:15 +08001978 if (usecase->type == PCM_CAPTURE ||
1979 usecase->type == TRANSCODE_LOOPBACK) {
1980 return false;
1981 }
1982
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001983 if(usecase->stream.out == NULL) {
1984 ALOGE("%s: stream.out is NULL", __func__);
1985 return false;
1986 }
1987
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301988 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001989 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1990 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1991 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301992 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1993 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1994 (!is_it_true_mode && adev->native_playback_enabled)){
1995 ret = true;
1996 ALOGD("napb: time to toggle native mode");
1997 }
1998 }
1999
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302000 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302001 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2002 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002003 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302004 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302005 ALOGD("Force a2dp device switch to update new encoder config");
2006 ret = true;
2007 }
2008
Manish Dewangan671a4202017-08-18 17:30:46 +05302009 if (usecase->stream.out->stream_config_changed) {
2010 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2011 return true;
2012 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302013 return ret;
2014}
2015
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302016bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2017{
2018 bool ret=false;
2019 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2020 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2021 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2022 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2023 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2024 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2025 ret = true;
2026
2027 return ret;
2028}
2029
2030bool is_a2dp_device(snd_device_t out_snd_device)
2031{
2032 bool ret=false;
2033 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2034 ret = true;
2035
2036 return ret;
2037}
2038
2039bool is_bt_soc_on(struct audio_device *adev)
2040{
2041 struct mixer_ctl *ctl;
2042 char *mixer_ctl_name = "BT SOC status";
2043 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2044 bool bt_soc_status = true;
2045 if (!ctl) {
2046 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2047 __func__, mixer_ctl_name);
2048 /*This is to ensure we dont break targets which dont have the kernel change*/
2049 return true;
2050 }
2051 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2052 ALOGD("BT SOC status: %d",bt_soc_status);
2053 return bt_soc_status;
2054}
2055
2056int out_standby_l(struct audio_stream *stream);
2057
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002058int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002060 snd_device_t out_snd_device = SND_DEVICE_NONE;
2061 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002062 struct audio_usecase *usecase = NULL;
2063 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002064 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002065 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302066 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002067 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002068 int status = 0;
Weiyin Jiang5d608082018-02-01 17:24:33 +08002069 audio_devices_t audio_device;
2070 audio_channel_mask_t channel_mask;
2071 int sample_rate;
2072 int acdb_id;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002073
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302074 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2075
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002076 usecase = get_usecase_from_list(adev, uc_id);
2077 if (usecase == NULL) {
2078 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2079 return -EINVAL;
2080 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002081
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002082 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002083 (usecase->type == VOIP_CALL) ||
2084 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302085 if(usecase->stream.out == NULL) {
2086 ALOGE("%s: stream.out is NULL", __func__);
2087 return -EINVAL;
2088 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002089 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002090 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002091 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002092 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302093 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
2094 if (usecase->stream.inout == NULL) {
2095 ALOGE("%s: stream.inout is NULL", __func__);
2096 return -EINVAL;
2097 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302098 stream_out.devices = usecase->stream.inout->out_config.devices;
2099 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2100 stream_out.format = usecase->stream.inout->out_config.format;
2101 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2102 out_snd_device = platform_get_output_snd_device(adev->platform,
2103 &stream_out);
2104 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302105 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002106 } else {
2107 /*
2108 * If the voice call is active, use the sound devices of voice call usecase
2109 * so that it would not result any device switch. All the usecases will
2110 * be switched to new device when select_devices() is called for voice call
2111 * usecase. This is to avoid switching devices for voice call when
2112 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002113 * choose voice call device only if the use case device is
2114 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002115 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002116 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002117 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002118 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002119 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2120 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302121 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2122 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002123 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002124 in_snd_device = vc_usecase->in_snd_device;
2125 out_snd_device = vc_usecase->out_snd_device;
2126 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002127 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002128 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002129 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002130 if ((voip_usecase != NULL) &&
2131 (usecase->type == PCM_PLAYBACK) &&
2132 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002133 out_snd_device_backend_match = platform_check_backends_match(
2134 voip_usecase->out_snd_device,
2135 platform_get_output_snd_device(
2136 adev->platform,
2137 usecase->stream.out));
2138 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002139 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002140 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2141 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002142 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002143 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002144 in_snd_device = voip_usecase->in_snd_device;
2145 out_snd_device = voip_usecase->out_snd_device;
2146 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002147 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002148 hfp_ucid = audio_extn_hfp_get_usecase();
2149 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002150 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002151 in_snd_device = hfp_usecase->in_snd_device;
2152 out_snd_device = hfp_usecase->out_snd_device;
2153 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002154 }
2155 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302156 if (usecase->stream.out == NULL) {
2157 ALOGE("%s: stream.out is NULL", __func__);
2158 return -EINVAL;
2159 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002160 usecase->devices = usecase->stream.out->devices;
2161 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002162 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002163 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002164 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002165 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleiz3ca773f2018-10-12 15:49:35 +08002166 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002167 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2168
2169 if ((usecase->stream.out != NULL &&
2170 voip_usecase != NULL &&
2171 usecase->stream.out->usecase == voip_usecase->id) &&
2172 adev->active_input &&
kunleiz3ca773f2018-10-12 15:49:35 +08002173 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002174 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002175 select_devices(adev, adev->active_input->usecase);
2176 }
2177 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002178 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302179 if (usecase->stream.in == NULL) {
2180 ALOGE("%s: stream.in is NULL", __func__);
2181 return -EINVAL;
2182 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002183 usecase->devices = usecase->stream.in->device;
2184 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002185 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002186 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002187 if (adev->active_input &&
2188 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302189 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002190 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2191 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2192 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2193 out_device = voip_usecase->stream.out->devices;
2194 else if (adev->primary_output && !adev->primary_output->standby)
2195 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002196 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002197 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2198 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002199 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002200 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002201 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002202 }
2203 }
2204
2205 if (out_snd_device == usecase->out_snd_device &&
2206 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302207
2208 if (!force_device_switch(usecase))
2209 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210 }
2211
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302212 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
2213 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
2214 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2215 return 0;
2216 }
2217
sangwoobc677242013-08-08 16:53:43 +09002218 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07002219 out_snd_device, platform_get_snd_device_name(out_snd_device),
2220 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222 /*
2223 * Limitation: While in call, to do a device switch we need to disable
2224 * and enable both RX and TX devices though one of them is same as current
2225 * device.
2226 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002227 if ((usecase->type == VOICE_CALL) &&
2228 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2229 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002230 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002231 }
2232
2233 if (((usecase->type == VOICE_CALL) ||
2234 (usecase->type == VOIP_CALL)) &&
2235 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2236 /* Disable sidetone only if voice/voip call already exists */
2237 if (voice_is_call_state_active(adev) ||
2238 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002239 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002240
2241 /* Disable aanc only if voice call exists */
2242 if (voice_is_call_state_active(adev))
2243 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002244 }
2245
Zhou Songc66eb7e2017-08-08 18:29:07 +08002246 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302247 (!audio_extn_a2dp_is_ready())) {
2248 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002249 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302250 }
2251
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002252 /* Disable current sound devices */
2253 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002254 disable_audio_route(adev, usecase);
2255 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256 }
2257
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002258 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002259 disable_audio_route(adev, usecase);
2260 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261 }
2262
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002263 /* Applicable only on the targets that has external modem.
2264 * New device information should be sent to modem before enabling
2265 * the devices to reduce in-call device switch time.
2266 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002267 if ((usecase->type == VOICE_CALL) &&
2268 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2269 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002270 status = platform_switch_voice_call_enable_device_config(adev->platform,
2271 out_snd_device,
2272 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002273 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002274
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002275 /* Enable new sound devices */
2276 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002277 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302278 if (platform_check_codec_asrc_support(adev->platform))
2279 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002280 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002281 }
2282
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002283 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302284 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002285 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002286 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002287
Avinash Vaish71a8b972014-07-24 15:36:33 +05302288 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002289 status = platform_switch_voice_call_device_post(adev->platform,
2290 out_snd_device,
2291 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302292 enable_audio_route_for_voice_usecases(adev, usecase);
2293 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002294
sangwoo170731f2013-06-08 15:36:36 +09002295 usecase->in_snd_device = in_snd_device;
2296 usecase->out_snd_device = out_snd_device;
2297
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302298 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2299 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302300 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002301 if ((24 == usecase->stream.out->bit_width) &&
2302 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2303 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2304 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2305 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2306 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2307 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2308 /*
2309 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2310 * configured device sample rate, if not update the COPP rate to be equal to the
2311 * device sample rate, else open COPP at stream sample rate
2312 */
2313 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2314 usecase->stream.out->sample_rate,
2315 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302316 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2317 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002318 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2319 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2320 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2321 }
2322
Weiyin Jiang5d608082018-02-01 17:24:33 +08002323 /* Cache stream information to be notified to gef clients */
2324 audio_device = usecase->stream.out->devices;
2325 channel_mask = usecase->stream.out->channel_mask;
2326 sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
2327 acdb_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302328 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002329 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002330
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002331 /* If input stream is already running then effect needs to be
2332 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002333 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2334 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002335 check_and_enable_effect(adev);
2336
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002337 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002338 /* Enable aanc only if voice call exists */
2339 if (voice_is_call_state_active(adev))
2340 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2341
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002342 /* Enable sidetone only if other voice/voip call already exists */
2343 if (voice_is_call_state_active(adev) ||
2344 voice_extn_compress_voip_is_started(adev))
2345 voice_set_sidetone(adev, out_snd_device, true);
2346 }
2347
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002348 /* Applicable only on the targets that has external modem.
2349 * Enable device command should be sent to modem only after
2350 * enabling voice call mixer controls
2351 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002352 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002353 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2354 out_snd_device,
2355 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302356
2357 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2358
2359 if (usecase->type == VOIP_CALL) {
2360 if (adev->active_input != NULL &&
2361 !adev->active_input->standby) {
2362 if (is_bt_soc_on(adev) == false){
2363 ALOGD("BT SCO MIC disconnected while in connection");
2364 if (adev->active_input->pcm != NULL)
2365 pcm_stop(adev->active_input->pcm);
2366 }
2367 }
2368 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2369 && usecase->stream.out->started) {
2370 if (is_bt_soc_on(adev) == false) {
2371 ALOGD("BT SCO/A2DP disconnected while in connection");
2372 out_standby_l(&usecase->stream.out->stream.common);
2373 }
2374 }
2375 } else if ((usecase->stream.out != NULL) &&
2376 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2377 usecase->stream.out->started) {
2378 if (is_bt_soc_on(adev) == false) {
2379 ALOGD("BT SCO/A2dp disconnected while in connection");
2380 out_standby_l(&usecase->stream.out->stream.common);
2381 }
2382 }
2383 }
2384
Weiyin Jiang5d608082018-02-01 17:24:33 +08002385 /* Notify device change info to effect clients registered
2386 * NOTE: device lock has to be unlock temporarily here.
2387 * To the worst case, we notify stale info to clients.
2388 */
2389 if (usecase->type == PCM_PLAYBACK) {
2390 pthread_mutex_unlock(&adev->lock);
2391 audio_extn_gef_notify_device_config(audio_device, channel_mask, sample_rate, acdb_id);
2392 pthread_mutex_lock(&adev->lock);
2393 }
2394
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302395 ALOGD("%s: done",__func__);
2396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002397 return status;
2398}
2399
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002400static int stop_input_stream(struct stream_in *in)
2401{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302402 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002403 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302404
2405 if (in == NULL) {
2406 ALOGE("%s: stream_in ptr is NULL", __func__);
2407 return -EINVAL;
2408 }
2409
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002410 struct audio_device *adev = in->dev;
2411
Eric Laurent994a6932013-07-17 11:51:42 -07002412 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002413 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002414 uc_info = get_usecase_from_list(adev, in->usecase);
2415 if (uc_info == NULL) {
2416 ALOGE("%s: Could not find the usecase (%d) in the list",
2417 __func__, in->usecase);
2418 return -EINVAL;
2419 }
2420
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002421 /* Close in-call recording streams */
2422 voice_check_and_stop_incall_rec_usecase(adev, in);
2423
Eric Laurent150dbfe2013-02-27 14:31:02 -08002424 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002425 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002426
2427 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002428 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002429
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002430 list_remove(&uc_info->list);
2431 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002433 adev->active_input = get_next_active_input(adev);
2434
Eric Laurent994a6932013-07-17 11:51:42 -07002435 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002436 return ret;
2437}
2438
2439int start_input_stream(struct stream_in *in)
2440{
2441 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002442 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002443 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302444
2445 if (in == NULL) {
2446 ALOGE("%s: stream_in ptr is NULL", __func__);
2447 return -EINVAL;
2448 }
2449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002451 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002452 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002453
Mingming Yin2664a5b2015-09-03 10:53:11 -07002454 if (get_usecase_from_list(adev, usecase) == NULL)
2455 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302456 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2457 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002458
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302459 if (CARD_STATUS_OFFLINE == in->card_status||
2460 CARD_STATUS_OFFLINE == adev->card_status) {
2461 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302462 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302463 goto error_config;
2464 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302465
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302466 if (audio_is_bluetooth_sco_device(in->device)) {
2467 if (!adev->bt_sco_on) {
2468 ALOGE("%s: SCO profile is not ready, return error", __func__);
2469 ret = -EIO;
2470 goto error_config;
2471 }
2472 }
2473
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002474 /* Check if source matches incall recording usecase criteria */
2475 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2476 if (ret)
2477 goto error_config;
2478 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002479 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2480
2481 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2482 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2483 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002484 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002485 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002486
Eric Laurentb23d5282013-05-14 15:27:20 -07002487 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488 if (in->pcm_device_id < 0) {
2489 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2490 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002491 ret = -EINVAL;
2492 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002494
2495 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002497
2498 if (!uc_info) {
2499 ret = -ENOMEM;
2500 goto error_config;
2501 }
2502
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503 uc_info->id = in->usecase;
2504 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002505 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002506 uc_info->devices = in->device;
2507 uc_info->in_snd_device = SND_DEVICE_NONE;
2508 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002510 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302511 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2512 adev->perf_lock_opts,
2513 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002514 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515
Haynes Mathew George16081042017-05-31 17:16:49 -07002516 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302517 ret = audio_extn_cin_start_input_stream(in);
2518 if (ret)
2519 goto error_open;
2520 else
2521 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002522 }
2523
Haynes Mathew George16081042017-05-31 17:16:49 -07002524 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002525 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002526 ALOGE("%s: pcm stream not ready", __func__);
2527 goto error_open;
2528 }
2529 ret = pcm_start(in->pcm);
2530 if (ret < 0) {
2531 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2532 goto error_open;
2533 }
2534 } else {
2535 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2536 unsigned int pcm_open_retry_count = 0;
2537
2538 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2539 flags |= PCM_MMAP | PCM_NOIRQ;
2540 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2541 } else if (in->realtime) {
2542 flags |= PCM_MMAP | PCM_NOIRQ;
2543 }
2544
Garmond Leunge2433c32017-09-28 21:51:22 -07002545 if (audio_extn_ffv_get_stream() == in) {
2546 ALOGD("%s: ffv stream, update pcm config", __func__);
2547 audio_extn_ffv_update_pcm_config(&config);
2548 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002549 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2550 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2551
2552 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002553 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002554 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002555 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002556 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002557 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2558 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2559 if (in->pcm != NULL) {
2560 pcm_close(in->pcm);
2561 in->pcm = NULL;
2562 }
2563 if (pcm_open_retry_count-- == 0) {
2564 ret = -EIO;
2565 goto error_open;
2566 }
2567 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2568 continue;
2569 }
2570 break;
2571 }
2572
2573 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002574 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002575 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002576 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002577 if (ret < 0) {
2578 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2579 pcm_close(in->pcm);
2580 in->pcm = NULL;
2581 goto error_open;
2582 }
2583 register_in_stream(in);
2584 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002585 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002586 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002587 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002588 if (ret < 0) {
2589 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002590 pcm_close(in->pcm);
2591 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002592 goto error_open;
2593 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002594 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002595 }
2596
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002597 check_and_enable_effect(adev);
2598
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302599done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302600 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002601 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002602
Eric Laurentc8400632013-02-14 19:04:54 -08002603 return ret;
2604
2605error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302606 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002608error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302609 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302610 /*
2611 * sleep 50ms to allow sufficient time for kernel
2612 * drivers to recover incases like SSR.
2613 */
2614 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002615 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002616
2617 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618}
2619
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002620void lock_input_stream(struct stream_in *in)
2621{
2622 pthread_mutex_lock(&in->pre_lock);
2623 pthread_mutex_lock(&in->lock);
2624 pthread_mutex_unlock(&in->pre_lock);
2625}
2626
2627void lock_output_stream(struct stream_out *out)
2628{
2629 pthread_mutex_lock(&out->pre_lock);
2630 pthread_mutex_lock(&out->lock);
2631 pthread_mutex_unlock(&out->pre_lock);
2632}
2633
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002634/* must be called with out->lock locked */
2635static int send_offload_cmd_l(struct stream_out* out, int command)
2636{
2637 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2638
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002639 if (!cmd) {
2640 ALOGE("failed to allocate mem for command 0x%x", command);
2641 return -ENOMEM;
2642 }
2643
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002644 ALOGVV("%s %d", __func__, command);
2645
2646 cmd->cmd = command;
2647 list_add_tail(&out->offload_cmd_list, &cmd->node);
2648 pthread_cond_signal(&out->offload_cond);
2649 return 0;
2650}
2651
2652/* must be called iwth out->lock locked */
2653static void stop_compressed_output_l(struct stream_out *out)
2654{
2655 out->offload_state = OFFLOAD_STATE_IDLE;
2656 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002657 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002658 if (out->compr != NULL) {
2659 compress_stop(out->compr);
2660 while (out->offload_thread_blocked) {
2661 pthread_cond_wait(&out->cond, &out->lock);
2662 }
2663 }
2664}
2665
Varun Balaraje49253e2017-07-06 19:48:56 +05302666bool is_interactive_usecase(audio_usecase_t uc_id)
2667{
2668 unsigned int i;
2669 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2670 if (uc_id == interactive_usecases[i])
2671 return true;
2672 }
2673 return false;
2674}
2675
2676static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2677{
2678 audio_usecase_t ret_uc = USECASE_INVALID;
2679 unsigned int intract_uc_index;
2680 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2681
2682 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2683 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2684 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2685 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2686 ret_uc = interactive_usecases[intract_uc_index];
2687 break;
2688 }
2689 }
2690
2691 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2692 return ret_uc;
2693}
2694
2695static void free_interactive_usecase(struct audio_device *adev,
2696 audio_usecase_t uc_id)
2697{
2698 unsigned int interact_uc_index;
2699 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2700
2701 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2702 if (interactive_usecases[interact_uc_index] == uc_id) {
2703 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2704 break;
2705 }
2706 }
2707 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2708}
2709
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002710bool is_offload_usecase(audio_usecase_t uc_id)
2711{
2712 unsigned int i;
2713 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2714 if (uc_id == offload_usecases[i])
2715 return true;
2716 }
2717 return false;
2718}
2719
Dhananjay Kumarac341582017-02-23 23:42:25 +05302720static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002721{
vivek mehta446c3962015-09-14 10:57:35 -07002722 audio_usecase_t ret_uc = USECASE_INVALID;
2723 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002724 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002725 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302726 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002727 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2728 else
2729 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002730
vivek mehta446c3962015-09-14 10:57:35 -07002731 pthread_mutex_lock(&adev->lock);
2732 if (get_usecase_from_list(adev, ret_uc) != NULL)
2733 ret_uc = USECASE_INVALID;
2734 pthread_mutex_unlock(&adev->lock);
2735
2736 return ret_uc;
2737 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002738
2739 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002740 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2741 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2742 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2743 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002744 break;
2745 }
2746 }
vivek mehta446c3962015-09-14 10:57:35 -07002747
2748 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2749 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002750}
2751
2752static void free_offload_usecase(struct audio_device *adev,
2753 audio_usecase_t uc_id)
2754{
vivek mehta446c3962015-09-14 10:57:35 -07002755 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002756 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002757
2758 if (!adev->multi_offload_enable)
2759 return;
2760
2761 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2762 if (offload_usecases[offload_uc_index] == uc_id) {
2763 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002764 break;
2765 }
2766 }
2767 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2768}
2769
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002770static void *offload_thread_loop(void *context)
2771{
2772 struct stream_out *out = (struct stream_out *) context;
2773 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002774 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002775
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002776 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2777 set_sched_policy(0, SP_FOREGROUND);
2778 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2779
2780 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002781 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002782 for (;;) {
2783 struct offload_cmd *cmd = NULL;
2784 stream_callback_event_t event;
2785 bool send_callback = false;
2786
2787 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2788 __func__, list_empty(&out->offload_cmd_list),
2789 out->offload_state);
2790 if (list_empty(&out->offload_cmd_list)) {
2791 ALOGV("%s SLEEPING", __func__);
2792 pthread_cond_wait(&out->offload_cond, &out->lock);
2793 ALOGV("%s RUNNING", __func__);
2794 continue;
2795 }
2796
2797 item = list_head(&out->offload_cmd_list);
2798 cmd = node_to_item(item, struct offload_cmd, node);
2799 list_remove(item);
2800
2801 ALOGVV("%s STATE %d CMD %d out->compr %p",
2802 __func__, out->offload_state, cmd->cmd, out->compr);
2803
2804 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2805 free(cmd);
2806 break;
2807 }
2808
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002809 // allow OFFLOAD_CMD_ERROR reporting during standby
2810 // this is needed to handle failures during compress_open
2811 // Note however that on a pause timeout, the stream is closed
2812 // and no offload usecase will be active. Therefore this
2813 // special case is needed for compress_open failures alone
2814 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2815 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002816 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002817 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002818 pthread_cond_signal(&out->cond);
2819 continue;
2820 }
2821 out->offload_thread_blocked = true;
2822 pthread_mutex_unlock(&out->lock);
2823 send_callback = false;
2824 switch(cmd->cmd) {
2825 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002826 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002827 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002828 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002829 send_callback = true;
2830 event = STREAM_CBK_EVENT_WRITE_READY;
2831 break;
2832 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002833 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302834 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002835 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302836 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002837 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302838 if (ret < 0)
2839 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302840 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302841 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002842 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002843 else
2844 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002845 if (-ENETRESET != ret && !(-EINTR == ret &&
2846 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302847 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302848 pthread_mutex_lock(&out->lock);
2849 out->send_new_metadata = 1;
2850 out->send_next_track_params = true;
2851 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302852 event = STREAM_CBK_EVENT_DRAIN_READY;
2853 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2854 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302855 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002856 break;
2857 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002858 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002859 ret = compress_drain(out->compr);
2860 ALOGD("copl(%p):out of compress_drain", out);
2861 // EINTR check avoids drain interruption due to SSR
2862 if (-ENETRESET != ret && !(-EINTR == ret &&
2863 CARD_STATUS_OFFLINE == out->card_status)) {
2864 send_callback = true;
2865 event = STREAM_CBK_EVENT_DRAIN_READY;
2866 } else
2867 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002868 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302869 case OFFLOAD_CMD_ERROR:
2870 ALOGD("copl(%p): sending error callback to AF", out);
2871 send_callback = true;
2872 event = STREAM_CBK_EVENT_ERROR;
2873 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002874 default:
2875 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2876 break;
2877 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002878 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002879 out->offload_thread_blocked = false;
2880 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002881 if (send_callback && out->client_callback) {
2882 ALOGVV("%s: sending client_callback event %d", __func__, event);
2883 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002884 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002885 free(cmd);
2886 }
2887
2888 pthread_cond_signal(&out->cond);
2889 while (!list_empty(&out->offload_cmd_list)) {
2890 item = list_head(&out->offload_cmd_list);
2891 list_remove(item);
2892 free(node_to_item(item, struct offload_cmd, node));
2893 }
2894 pthread_mutex_unlock(&out->lock);
2895
2896 return NULL;
2897}
2898
2899static int create_offload_callback_thread(struct stream_out *out)
2900{
2901 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2902 list_init(&out->offload_cmd_list);
2903 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2904 offload_thread_loop, out);
2905 return 0;
2906}
2907
2908static int destroy_offload_callback_thread(struct stream_out *out)
2909{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002910 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002911 stop_compressed_output_l(out);
2912 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2913
2914 pthread_mutex_unlock(&out->lock);
2915 pthread_join(out->offload_thread, (void **) NULL);
2916 pthread_cond_destroy(&out->offload_cond);
2917
2918 return 0;
2919}
2920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002921static int stop_output_stream(struct stream_out *out)
2922{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302923 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002924 struct audio_usecase *uc_info;
2925 struct audio_device *adev = out->dev;
2926
Eric Laurent994a6932013-07-17 11:51:42 -07002927 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002928 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002929 uc_info = get_usecase_from_list(adev, out->usecase);
2930 if (uc_info == NULL) {
2931 ALOGE("%s: Could not find the usecase (%d) in the list",
2932 __func__, out->usecase);
2933 return -EINVAL;
2934 }
2935
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002936 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302937 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002938 if (adev->visualizer_stop_output != NULL)
2939 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002940
2941 audio_extn_dts_remove_state_notifier_node(out->usecase);
2942
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002943 if (adev->offload_effects_stop_output != NULL)
2944 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2945 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002946
Arun Mirpurief53ce52018-09-11 18:00:09 -07002947 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2948 voice_set_device_mute_flag(adev, false);
2949
Eric Laurent150dbfe2013-02-27 14:31:02 -08002950 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002951 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002952
2953 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002954 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002955
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002956 if (is_offload_usecase(out->usecase)) {
2957 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2958 adev->dsp_bit_width_enforce_mode,
2959 false);
2960 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07002961 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2962 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
2963 false);
2964
2965 if (ret != 0)
2966 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
2967 /* default service interval was successfully updated,
2968 reopen USB backend with new service interval */
2969 ret = 0;
2970 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002971
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002972 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302973 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002974 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302975 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002976 ALOGV("Disable passthrough , reset mixer to pcm");
2977 /* NO_PASSTHROUGH */
2978 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002979 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002980 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2981 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002982
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302983 /* Must be called after removing the usecase from list */
2984 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05302985 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302986
Manish Dewangan21a850a2017-08-14 12:03:55 +05302987 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002988 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2989 if (ret < 0)
2990 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2991 }
2992
Garmond Leung5fd0b552018-04-17 11:56:12 -07002993 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002994 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 return ret;
2996}
2997
2998int start_output_stream(struct stream_out *out)
2999{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001 struct audio_usecase *uc_info;
3002 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003003 char mixer_ctl_name[128];
3004 struct mixer_ctl *ctl = NULL;
3005 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303006 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007
Haynes Mathew George380745d2017-10-04 15:27:45 -07003008 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003009 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3010 ret = -EINVAL;
3011 goto error_config;
3012 }
3013
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303014 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
3015 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
3016 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303017
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303018 if (CARD_STATUS_OFFLINE == out->card_status ||
3019 CARD_STATUS_OFFLINE == adev->card_status) {
3020 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303021 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303022 goto error_config;
3023 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303024
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303025 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
3026 if (!audio_extn_a2dp_is_ready()) {
3027 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303028 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303029 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303030 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3031 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3032 ret = -EAGAIN;
3033 goto error_config;
3034 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303035 }
3036 }
3037 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303038 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3039 if (!adev->bt_sco_on) {
3040 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3041 //combo usecase just by pass a2dp
3042 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3043 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3044 } else {
3045 ALOGE("%s: SCO profile is not ready, return error", __func__);
3046 ret = -EAGAIN;
3047 goto error_config;
3048 }
3049 }
3050 }
3051
Eric Laurentb23d5282013-05-14 15:27:20 -07003052 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053 if (out->pcm_device_id < 0) {
3054 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3055 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003056 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003057 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058 }
3059
3060 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003061
3062 if (!uc_info) {
3063 ret = -ENOMEM;
3064 goto error_config;
3065 }
3066
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067 uc_info->id = out->usecase;
3068 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003069 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003070 uc_info->devices = out->devices;
3071 uc_info->in_snd_device = SND_DEVICE_NONE;
3072 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003073
3074 /* This must be called before adding this usecase to the list */
3075 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3076 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3077 /* USB backend is not reopened immediately.
3078 This is eventually done as part of select_devices */
3079 }
3080
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003081 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303083 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3084 adev->perf_lock_opts,
3085 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303086
3087 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303088 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303089 if (audio_extn_passthru_is_enabled() &&
3090 audio_extn_passthru_is_passthrough_stream(out)) {
3091 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303092 }
3093 }
3094
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303095 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3096 (!audio_extn_a2dp_is_ready())) {
3097 if (!a2dp_combo) {
3098 check_a2dp_restore_l(adev, out, false);
3099 } else {
3100 audio_devices_t dev = out->devices;
3101 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3102 select_devices(adev, out->usecase);
3103 out->devices = dev;
3104 }
3105 } else {
3106 select_devices(adev, out->usecase);
3107 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003108
Arun Mirpurief53ce52018-09-11 18:00:09 -07003109 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3110 voice_set_device_mute_flag(adev, true);
3111
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003112 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3113 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003114
3115 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuriebe78a72018-10-04 18:23:46 -07003116 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003117 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3118 ALOGE("%s: pcm stream not ready", __func__);
3119 goto error_open;
3120 }
3121 ret = pcm_start(out->pcm);
3122 if (ret < 0) {
3123 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3124 goto error_open;
3125 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07003126 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003127 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003128 unsigned int flags = PCM_OUT;
3129 unsigned int pcm_open_retry_count = 0;
3130 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3131 flags |= PCM_MMAP | PCM_NOIRQ;
3132 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003133 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003134 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003135 } else
3136 flags |= PCM_MONOTONIC;
3137
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003138 if ((adev->vr_audio_mode_enabled) &&
3139 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3140 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3141 "PCM_Dev %d Topology", out->pcm_device_id);
3142 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3143 if (!ctl) {
3144 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3145 __func__, mixer_ctl_name);
3146 } else {
3147 //if success use ULLPP
3148 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3149 __func__, mixer_ctl_name, out->pcm_device_id);
3150 //There is a still a possibility that some sessions
3151 // that request for FAST|RAW when 3D audio is active
3152 //can go through ULLPP. Ideally we expects apps to
3153 //listen to audio focus and stop concurrent playback
3154 //Also, we will look for mode flag (voice_in_communication)
3155 //before enabling the realtime flag.
3156 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3157 }
3158 }
3159
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003160 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003161 ATRACE_BEGIN("pcm_open");
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003162 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3163 flags, &out->config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003164 ATRACE_END();
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003165 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3166 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3167 if (out->pcm != NULL) {
3168 pcm_close(out->pcm);
3169 out->pcm = NULL;
3170 }
3171 if (pcm_open_retry_count-- == 0) {
3172 ret = -EIO;
3173 goto error_open;
3174 }
3175 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3176 continue;
3177 }
3178 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003179 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003180
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003181 ALOGV("%s: pcm_prepare", __func__);
3182 if (pcm_is_ready(out->pcm)) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003183 ATRACE_BEGIN("pcm_prepare");
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003184 ret = pcm_prepare(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003185 ATRACE_END();
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003186 if (ret < 0) {
3187 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3188 pcm_close(out->pcm);
3189 out->pcm = NULL;
3190 goto error_open;
3191 }
3192 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05303193 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303194 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08003195 // apply volume for voip playback after path is set up
3196 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3197 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003198 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003199 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303200 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003201 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3202 adev->dsp_bit_width_enforce_mode,
3203 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003205 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003206 out->compr = compress_open(adev->snd_card,
3207 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003208 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003209 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003210 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003211 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003212 compress_close(out->compr);
3213 out->compr = NULL;
3214 ret = -EIO;
3215 goto error_open;
3216 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303217 /* compress_open sends params of the track, so reset the flag here */
3218 out->is_compr_metadata_avail = false;
3219
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003220 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003221 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003222
Fred Oh3f43e742015-03-04 18:42:34 -08003223 /* Since small bufs uses blocking writes, a write will be blocked
3224 for the default max poll time (20s) in the event of an SSR.
3225 Reduce the poll time to observe and deal with SSR faster.
3226 */
Ashish Jain5106d362016-05-11 19:23:33 +05303227 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003228 compress_set_max_poll_wait(out->compr, 1000);
3229 }
3230
Manish Dewangan69426c82017-01-30 17:35:36 +05303231 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303232 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303233
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003234 audio_extn_dts_create_state_notifier_node(out->usecase);
3235 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3236 popcount(out->channel_mask),
3237 out->playback_started);
3238
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003239#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303240 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003241 audio_extn_dolby_send_ddp_endp_params(adev);
3242#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303243 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3244 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003245 if (adev->visualizer_start_output != NULL)
3246 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3247 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303248 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003249 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003250 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003251 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003252
3253 if (ret == 0) {
3254 register_out_stream(out);
3255 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003256 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3257 ALOGE("%s: pcm stream not ready", __func__);
3258 goto error_open;
3259 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003260 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003261 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003262 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003263 if (ret < 0)
3264 goto error_open;
3265 }
3266 }
3267
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303268 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003269 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003270
Manish Dewangan21a850a2017-08-14 12:03:55 +05303271 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003272 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003273 if (ret < 0)
3274 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3275 }
3276
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003277 // consider a scenario where on pause lower layers are tear down.
3278 // so on resume, swap mixer control need to be sent only when
3279 // backend is active, hence rather than sending from enable device
3280 // sending it from start of streamtream
3281
3282 platform_set_swap_channels(adev, true);
3283
Haynes Mathew George380745d2017-10-04 15:27:45 -07003284 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003285 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003286error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303287 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003288 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003289error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303290 /*
3291 * sleep 50ms to allow sufficient time for kernel
3292 * drivers to recover incases like SSR.
3293 */
3294 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003295 ATRACE_END();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003296 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003297}
3298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003299static int check_input_parameters(uint32_t sample_rate,
3300 audio_format_t format,
3301 int channel_count)
3302{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003303 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303305 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3306 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3307 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003308 !voice_extn_compress_voip_is_format_supported(format) &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003309 !audio_extn_compr_cap_format_supported(format))
3310 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003311
3312 switch (channel_count) {
3313 case 1:
3314 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303315 case 3:
3316 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003317 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003318 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003319 break;
3320 default:
3321 ret = -EINVAL;
3322 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003323
3324 switch (sample_rate) {
3325 case 8000:
3326 case 11025:
3327 case 12000:
3328 case 16000:
3329 case 22050:
3330 case 24000:
3331 case 32000:
3332 case 44100:
3333 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003334 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303335 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003336 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303337 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338 break;
3339 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003340 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341 }
3342
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003343 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344}
3345
Naresh Tanniru04f71882018-06-26 17:46:22 +05303346
3347/** Add a value in a list if not already present.
3348 * @return true if value was successfully inserted or already present,
3349 * false if the list is full and does not contain the value.
3350 */
3351static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3352 for (size_t i = 0; i < list_length; i++) {
3353 if (list[i] == value) return true; // value is already present
3354 if (list[i] == 0) { // no values in this slot
3355 list[i] = value;
3356 return true; // value inserted
3357 }
3358 }
3359 return false; // could not insert value
3360}
3361
3362/** Add channel_mask in supported_channel_masks if not already present.
3363 * @return true if channel_mask was successfully inserted or already present,
3364 * false if supported_channel_masks is full and does not contain channel_mask.
3365 */
3366static void register_channel_mask(audio_channel_mask_t channel_mask,
3367 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3368 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3369 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3370}
3371
3372/** Add format in supported_formats if not already present.
3373 * @return true if format was successfully inserted or already present,
3374 * false if supported_formats is full and does not contain format.
3375 */
3376static void register_format(audio_format_t format,
3377 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3378 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3379 "%s: stream can not declare supporting its format %x", __func__, format);
3380}
3381/** Add sample_rate in supported_sample_rates if not already present.
3382 * @return true if sample_rate was successfully inserted or already present,
3383 * false if supported_sample_rates is full and does not contain sample_rate.
3384 */
3385static void register_sample_rate(uint32_t sample_rate,
3386 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3387 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3388 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3389}
3390
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391static size_t get_input_buffer_size(uint32_t sample_rate,
3392 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003393 int channel_count,
3394 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395{
3396 size_t size = 0;
3397
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003398 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3399 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003401 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003402 if (is_low_latency)
3403 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303404
3405 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003407 /* make sure the size is multiple of 32 bytes
3408 * At 48 kHz mono 16-bit PCM:
3409 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3410 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
3411 */
3412 size += 0x1f;
3413 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003414
3415 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416}
3417
Ashish Jain058165c2016-09-28 23:18:48 +05303418static size_t get_output_period_size(uint32_t sample_rate,
3419 audio_format_t format,
3420 int channel_count,
3421 int duration /*in millisecs*/)
3422{
3423 size_t size = 0;
3424 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3425
3426 if ((duration == 0) || (sample_rate == 0) ||
3427 (bytes_per_sample == 0) || (channel_count == 0)) {
3428 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3429 bytes_per_sample, channel_count);
3430 return -EINVAL;
3431 }
3432
3433 size = (sample_rate *
3434 duration *
3435 bytes_per_sample *
3436 channel_count) / 1000;
3437 /*
3438 * To have same PCM samples for all channels, the buffer size requires to
3439 * be multiple of (number of channels * bytes per sample)
3440 * For writes to succeed, the buffer must be written at address which is multiple of 32
3441 */
3442 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3443
3444 return (size/(channel_count * bytes_per_sample));
3445}
3446
Zhou Song48453a02018-01-10 17:50:59 +08003447static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303448{
3449 uint64_t actual_frames_rendered = 0;
3450 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3451
3452 /* This adjustment accounts for buffering after app processor.
3453 * It is based on estimated DSP latency per use case, rather than exact.
3454 */
3455 int64_t platform_latency = platform_render_latency(out->usecase) *
3456 out->sample_rate / 1000000LL;
3457
Zhou Song48453a02018-01-10 17:50:59 +08003458 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303459 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3460 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3461 * hence only estimate.
3462 */
3463 int64_t signed_frames = out->written - kernel_buffer_size;
3464
3465 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3466
Zhou Song48453a02018-01-10 17:50:59 +08003467 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303468 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003469 if (timestamp != NULL )
3470 *timestamp = out->writeAt;
3471 } else if (timestamp != NULL) {
3472 clock_gettime(CLOCK_MONOTONIC, timestamp);
3473 }
3474 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303475
3476 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3477 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3478 (long long int)out->written, (int)kernel_buffer_size,
3479 audio_bytes_per_sample(out->compr_config.codec->format),
3480 popcount(out->channel_mask));
3481
3482 return actual_frames_rendered;
3483}
3484
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3486{
3487 struct stream_out *out = (struct stream_out *)stream;
3488
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003489 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490}
3491
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003492static int out_set_sample_rate(struct audio_stream *stream __unused,
3493 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494{
3495 return -ENOSYS;
3496}
3497
3498static size_t out_get_buffer_size(const struct audio_stream *stream)
3499{
3500 struct stream_out *out = (struct stream_out *)stream;
3501
Varun Balaraje49253e2017-07-06 19:48:56 +05303502 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303503 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303504 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303505 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3506 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3507 else
3508 return out->compr_config.fragment_size;
3509 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003510 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003511 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3512 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 +05303513 else if (is_offload_usecase(out->usecase) &&
3514 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303515 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003516
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003517 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003518 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519}
3520
3521static uint32_t out_get_channels(const struct audio_stream *stream)
3522{
3523 struct stream_out *out = (struct stream_out *)stream;
3524
3525 return out->channel_mask;
3526}
3527
3528static audio_format_t out_get_format(const struct audio_stream *stream)
3529{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003530 struct stream_out *out = (struct stream_out *)stream;
3531
3532 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533}
3534
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003535static int out_set_format(struct audio_stream *stream __unused,
3536 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003537{
3538 return -ENOSYS;
3539}
3540
3541static int out_standby(struct audio_stream *stream)
3542{
3543 struct stream_out *out = (struct stream_out *)stream;
3544 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003545 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003546
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303547 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3548 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003550 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003552 if (adev->adm_deregister_stream)
3553 adev->adm_deregister_stream(adev->adm_data, out->handle);
3554
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003555 if (is_offload_usecase(out->usecase))
3556 stop_compressed_output_l(out);
3557
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003558 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003560 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3561 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303562 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003563 pthread_mutex_unlock(&adev->lock);
3564 pthread_mutex_unlock(&out->lock);
3565 ALOGD("VOIP output entered standby");
3566 return 0;
3567 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003568 if (out->pcm) {
3569 pcm_close(out->pcm);
3570 out->pcm = NULL;
3571 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003572 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3573 do_stop = out->playback_started;
3574 out->playback_started = false;
3575 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003576 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003577 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303578 out->send_next_track_params = false;
3579 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003580 out->gapless_mdata.encoder_delay = 0;
3581 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003582 if (out->compr != NULL) {
3583 compress_close(out->compr);
3584 out->compr = NULL;
3585 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003586 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003587 if (do_stop) {
3588 stop_output_stream(out);
3589 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003590 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591 }
3592 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303593 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003594 return 0;
3595}
3596
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303597static int out_on_error(struct audio_stream *stream)
3598{
3599 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003600 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303601
3602 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003603 // always send CMD_ERROR for offload streams, this
3604 // is needed e.g. when SSR happens within compress_open
3605 // since the stream is active, offload_callback_thread is also active.
3606 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3607 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003608 }
3609 pthread_mutex_unlock(&out->lock);
3610
3611 status = out_standby(&out->stream.common);
3612
3613 lock_output_stream(out);
3614 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003615 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303616 }
3617 pthread_mutex_unlock(&out->lock);
3618
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003619 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303620}
3621
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303622/*
3623 *standby implementation without locks, assumes that the callee already
3624 *has taken adev and out lock.
3625 */
3626int out_standby_l(struct audio_stream *stream)
3627{
3628 struct stream_out *out = (struct stream_out *)stream;
3629 struct audio_device *adev = out->dev;
3630
3631 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3632 stream, out->usecase, use_case_table[out->usecase]);
3633
3634 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003635 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303636 if (adev->adm_deregister_stream)
3637 adev->adm_deregister_stream(adev->adm_data, out->handle);
3638
3639 if (is_offload_usecase(out->usecase))
3640 stop_compressed_output_l(out);
3641
3642 out->standby = true;
3643 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3644 voice_extn_compress_voip_close_output_stream(stream);
3645 out->started = 0;
3646 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003647 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303648 return 0;
3649 } else if (!is_offload_usecase(out->usecase)) {
3650 if (out->pcm) {
3651 pcm_close(out->pcm);
3652 out->pcm = NULL;
3653 }
3654 } else {
3655 ALOGD("copl(%p):standby", out);
3656 out->send_next_track_params = false;
3657 out->is_compr_metadata_avail = false;
3658 out->gapless_mdata.encoder_delay = 0;
3659 out->gapless_mdata.encoder_padding = 0;
3660 if (out->compr != NULL) {
3661 compress_close(out->compr);
3662 out->compr = NULL;
3663 }
3664 }
3665 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003666 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303667 }
3668 ALOGD("%s: exit", __func__);
3669 return 0;
3670}
3671
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003672static int out_dump(const struct audio_stream *stream __unused,
3673 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674{
3675 return 0;
3676}
3677
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003678static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3679{
3680 int ret = 0;
3681 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003682
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003683 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003684 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003685 return -EINVAL;
3686 }
3687
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303688 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003689
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003690 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3691 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303692 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003693 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003694 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3695 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303696 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003697 }
3698
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003699 ALOGV("%s new encoder delay %u and padding %u", __func__,
3700 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3701
3702 return 0;
3703}
3704
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003705static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3706{
3707 return out == adev->primary_output || out == adev->voice_tx_output;
3708}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003709
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303710// note: this call is safe only if the stream_cb is
3711// removed first in close_output_stream (as is done now).
3712static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3713{
3714 if (!stream || !parms)
3715 return;
3716
3717 struct stream_out *out = (struct stream_out *)stream;
3718 struct audio_device *adev = out->dev;
3719
3720 card_status_t status;
3721 int card;
3722 if (parse_snd_card_status(parms, &card, &status) < 0)
3723 return;
3724
3725 pthread_mutex_lock(&adev->lock);
3726 bool valid_cb = (card == adev->snd_card);
3727 pthread_mutex_unlock(&adev->lock);
3728
3729 if (!valid_cb)
3730 return;
3731
3732 lock_output_stream(out);
3733 if (out->card_status != status)
3734 out->card_status = status;
3735 pthread_mutex_unlock(&out->lock);
3736
3737 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3738 use_case_table[out->usecase],
3739 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3740
3741 if (status == CARD_STATUS_OFFLINE)
3742 out_on_error(stream);
3743
3744 return;
3745}
3746
Kevin Rocardfce19002017-08-07 19:21:36 -07003747static int get_alive_usb_card(struct str_parms* parms) {
3748 int card;
3749 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
3750 !audio_extn_usb_alive(card)) {
3751 return card;
3752 }
3753 return -ENODEV;
3754}
3755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3757{
3758 struct stream_out *out = (struct stream_out *)stream;
3759 struct audio_device *adev = out->dev;
3760 struct str_parms *parms;
3761 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003762 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303763 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003764 bool reconfig = false;
3765 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766
sangwoobc677242013-08-08 16:53:43 +09003767 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003768 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303770 if (!parms)
3771 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003772 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3773 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003775 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003776 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003778 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003779 * When HDMI cable is unplugged the music playback is paused and
3780 * the policy manager sends routing=0. But the audioflinger continues
3781 * to write data until standby time (3sec). As the HDMI core is
3782 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003783 * Avoid this by routing audio to speaker until standby.
3784 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003785 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3786 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303787 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003788 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3789 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003790 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303791 /*
3792 * When A2DP is disconnected the
3793 * music playback is paused and the policy manager sends routing=0
3794 * But the audioflingercontinues to write data until standby time
3795 * (3sec). As BT is turned off, the write gets blocked.
3796 * Avoid this by routing audio to speaker until standby.
3797 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003798 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07003799 (val == AUDIO_DEVICE_NONE) &&
3800 !audio_extn_a2dp_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303801 val = AUDIO_DEVICE_OUT_SPEAKER;
3802 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05303803 /*
3804 * When USB headset is disconnected the music platback paused
3805 * and the policy manager send routing=0. But if the USB is connected
3806 * back before the standby time, AFE is not closed and opened
3807 * when USB is connected back. So routing to speker will guarantee
3808 * AFE reconfiguration and AFE will be opend once USB is connected again
3809 */
3810 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
3811 (val == AUDIO_DEVICE_NONE) &&
3812 !audio_extn_usb_connected(parms)) {
3813 val = AUDIO_DEVICE_OUT_SPEAKER;
3814 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303815 /* To avoid a2dp to sco overlapping / BT device improper state
3816 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303817 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303818 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3819 if (!audio_extn_a2dp_is_ready()) {
3820 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3821 //combo usecase just by pass a2dp
3822 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303823 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303824 } else {
3825 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3826 /* update device to a2dp and don't route as BT returned error
3827 * However it is still possible a2dp routing called because
3828 * of current active device disconnection (like wired headset)
3829 */
3830 out->devices = val;
3831 pthread_mutex_unlock(&out->lock);
3832 pthread_mutex_unlock(&adev->lock);
3833 goto error;
3834 }
3835 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303836 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003837
3838 audio_devices_t new_dev = val;
3839
3840 // Workaround: If routing to an non existing usb device, fail gracefully
3841 // The routing request will otherwise block during 10 second
3842 int card;
3843 if (audio_is_usb_out_device(new_dev) &&
3844 (card = get_alive_usb_card(parms)) >= 0) {
3845
3846 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
3847 pthread_mutex_unlock(&adev->lock);
3848 pthread_mutex_unlock(&out->lock);
3849 ret = -ENOSYS;
3850 goto routing_fail;
3851 }
3852
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003853 /*
3854 * select_devices() call below switches all the usecases on the same
3855 * backend to the new device. Refer to check_usecases_codec_backend() in
3856 * the select_devices(). But how do we undo this?
3857 *
3858 * For example, music playback is active on headset (deep-buffer usecase)
3859 * and if we go to ringtones and select a ringtone, low-latency usecase
3860 * will be started on headset+speaker. As we can't enable headset+speaker
3861 * and headset devices at the same time, select_devices() switches the music
3862 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3863 * So when the ringtone playback is completed, how do we undo the same?
3864 *
3865 * We are relying on the out_set_parameters() call on deep-buffer output,
3866 * once the ringtone playback is ended.
3867 * NOTE: We should not check if the current devices are same as new devices.
3868 * Because select_devices() must be called to switch back the music
3869 * playback to headset.
3870 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003871 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003872 audio_devices_t new_dev = val;
3873 bool same_dev = out->devices == new_dev;
3874 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003875
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003876 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08003877 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003878 if (adev->mode == AUDIO_MODE_IN_CALL) {
3879 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003880 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3881 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
3882 audio_extn_usb_set_service_interval(true /*playback*/,
3883 service_interval,
3884 &reconfig);
3885 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
3886 }
3887 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003888 }
3889 } else {
3890 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003891 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003892 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003893 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003894
3895 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003896 if (!same_dev) {
3897 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303898 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3899 adev->perf_lock_opts,
3900 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003901 if (adev->adm_on_routing_change)
3902 adev->adm_on_routing_change(adev->adm_data,
3903 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003904 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303905 if (!bypass_a2dp) {
3906 select_devices(adev, out->usecase);
3907 } else {
3908 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3909 select_devices(adev, out->usecase);
3910 out->devices = new_dev;
3911 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003912
3913 if (!same_dev) {
3914 // on device switch force swap, lower functions will make sure
3915 // to check if swap is allowed or not.
3916 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05303917 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003918 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303919 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3920 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003921 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303922 pthread_mutex_lock(&out->compr_mute_lock);
3923 out->a2dp_compress_mute = false;
3924 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3925 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08003926 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
3927 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303928 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003929 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003930 }
3931
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003932 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003933 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003934 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003935 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003936
3937 if (out == adev->primary_output) {
3938 pthread_mutex_lock(&adev->lock);
3939 audio_extn_set_parameters(adev, parms);
3940 pthread_mutex_unlock(&adev->lock);
3941 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003942 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003943 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003944 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003945
3946 audio_extn_dts_create_state_notifier_node(out->usecase);
3947 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3948 popcount(out->channel_mask),
3949 out->playback_started);
3950
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003951 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003952 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003953
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303954 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3955 if (err >= 0) {
3956 strlcpy(out->profile, value, sizeof(out->profile));
3957 ALOGV("updating stream profile with value '%s'", out->profile);
3958 lock_output_stream(out);
3959 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3960 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07003961 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303962 out->sample_rate, out->bit_width,
3963 out->channel_mask, out->profile,
3964 &out->app_type_cfg);
3965 pthread_mutex_unlock(&out->lock);
3966 }
3967
Alexy Joseph98988832017-01-13 14:56:59 -08003968 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08003969 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
3970 // and vendor.audio.hal.output.suspend.supported is set to true
3971 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08003972 //check suspend parameter only for low latency and if the property
3973 //is enabled
3974 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3975 ALOGI("%s: got suspend_playback %s", __func__, value);
3976 lock_output_stream(out);
3977 if (!strncmp(value, "false", 5)) {
3978 //suspend_playback=false is supposed to set QOS value back to 75%
3979 //the mixer control sent with value Enable will achieve that
3980 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3981 } else if (!strncmp (value, "true", 4)) {
3982 //suspend_playback=true is supposed to remove QOS value
3983 //resetting the mixer control will set the default value
3984 //for the mixer control which is Disable and this removes the QOS vote
3985 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3986 } else {
3987 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3988 " got %s", __func__, value);
3989 ret = -1;
3990 }
3991
3992 if (ret != 0) {
3993 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3994 __func__, out->pm_qos_mixer_path, ret);
3995 }
3996
3997 pthread_mutex_unlock(&out->lock);
3998 }
3999 }
4000 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004001 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304002error:
Eric Laurent994a6932013-07-17 11:51:42 -07004003 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004004 return ret;
4005}
4006
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004007static bool stream_get_parameter_channels(struct str_parms *query,
4008 struct str_parms *reply,
4009 audio_channel_mask_t *supported_channel_masks) {
4010 int ret = -1;
4011 char value[512];
4012 bool first = true;
4013 size_t i, j;
4014
4015 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4016 ret = 0;
4017 value[0] = '\0';
4018 i = 0;
4019 while (supported_channel_masks[i] != 0) {
4020 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4021 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4022 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304023 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004024
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304025 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004026 first = false;
4027 break;
4028 }
4029 }
4030 i++;
4031 }
4032 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4033 }
4034 return ret == 0;
4035}
4036
4037static bool stream_get_parameter_formats(struct str_parms *query,
4038 struct str_parms *reply,
4039 audio_format_t *supported_formats) {
4040 int ret = -1;
4041 char value[256];
4042 size_t i, j;
4043 bool first = true;
4044
4045 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4046 ret = 0;
4047 value[0] = '\0';
4048 i = 0;
4049 while (supported_formats[i] != 0) {
4050 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4051 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4052 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304053 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004054 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304055 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004056 first = false;
4057 break;
4058 }
4059 }
4060 i++;
4061 }
4062 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4063 }
4064 return ret == 0;
4065}
4066
4067static bool stream_get_parameter_rates(struct str_parms *query,
4068 struct str_parms *reply,
4069 uint32_t *supported_sample_rates) {
4070
4071 int i;
4072 char value[256];
4073 int ret = -1;
4074 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4075 ret = 0;
4076 value[0] = '\0';
4077 i=0;
4078 int cursor = 0;
4079 while (supported_sample_rates[i]) {
4080 int avail = sizeof(value) - cursor;
4081 ret = snprintf(value + cursor, avail, "%s%d",
4082 cursor > 0 ? "|" : "",
4083 supported_sample_rates[i]);
4084 if (ret < 0 || ret >= avail) {
4085 // if cursor is at the last element of the array
4086 // overwrite with \0 is duplicate work as
4087 // snprintf already put a \0 in place.
4088 // else
4089 // we had space to write the '|' at value[cursor]
4090 // (which will be overwritten) or no space to fill
4091 // the first element (=> cursor == 0)
4092 value[cursor] = '\0';
4093 break;
4094 }
4095 cursor += ret;
4096 ++i;
4097 }
4098 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4099 value);
4100 }
4101 return ret >= 0;
4102}
4103
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004104static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4105{
4106 struct stream_out *out = (struct stream_out *)stream;
4107 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004108 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004109 char value[256];
4110 struct str_parms *reply = str_parms_create();
4111 size_t i, j;
4112 int ret;
4113 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004114
4115 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004116 if (reply) {
4117 str_parms_destroy(reply);
4118 }
4119 if (query) {
4120 str_parms_destroy(query);
4121 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004122 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4123 return NULL;
4124 }
4125
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004126 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004127 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4128 if (ret >= 0) {
4129 value[0] = '\0';
4130 i = 0;
4131 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004132 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4133 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004134 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004135 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004136 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004137 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004138 first = false;
4139 break;
4140 }
4141 }
4142 i++;
4143 }
4144 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4145 str = str_parms_to_str(reply);
4146 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004147 voice_extn_out_get_parameters(out, query, reply);
4148 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004149 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004150
Alexy Joseph62142aa2015-11-16 15:10:34 -08004151
4152 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4153 if (ret >= 0) {
4154 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304155 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4156 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004157 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304158 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004159 } else {
4160 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304161 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004162 }
4163 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004164 if (str)
4165 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004166 str = str_parms_to_str(reply);
4167 }
4168
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004169 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4170 if (ret >= 0) {
4171 value[0] = '\0';
4172 i = 0;
4173 first = true;
4174 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004175 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4176 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004177 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004178 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004179 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004180 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004181 first = false;
4182 break;
4183 }
4184 }
4185 i++;
4186 }
4187 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004188 if (str)
4189 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004190 str = str_parms_to_str(reply);
4191 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004192
4193 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4194 if (ret >= 0) {
4195 value[0] = '\0';
4196 i = 0;
4197 first = true;
4198 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004199 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4200 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004201 if (!first) {
4202 strlcat(value, "|", sizeof(value));
4203 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004204 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004205 first = false;
4206 break;
4207 }
4208 }
4209 i++;
4210 }
4211 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4212 if (str)
4213 free(str);
4214 str = str_parms_to_str(reply);
4215 }
4216
Alexy Joseph98988832017-01-13 14:56:59 -08004217 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4218 //only low latency track supports suspend_resume
4219 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004220 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004221 if (str)
4222 free(str);
4223 str = str_parms_to_str(reply);
4224 }
4225
4226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004227 str_parms_destroy(query);
4228 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004229 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004230 return str;
4231}
4232
4233static uint32_t out_get_latency(const struct audio_stream_out *stream)
4234{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004235 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004236 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004237 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004238
Alexy Josephaa54c872014-12-03 02:46:47 -08004239 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304240 lock_output_stream(out);
4241 latency = audio_extn_utils_compress_get_dsp_latency(out);
4242 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004243 } else if ((out->realtime) ||
4244 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004245 // since the buffer won't be filled up faster than realtime,
4246 // return a smaller number
4247 if (out->config.rate)
4248 period_ms = (out->af_period_multiplier * out->config.period_size *
4249 1000) / (out->config.rate);
4250 else
4251 period_ms = 0;
4252 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004253 } else {
4254 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004255 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004256 }
4257
yidongh0515e042017-07-06 15:00:34 +08004258 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004259 latency += audio_extn_a2dp_get_encoder_latency();
4260
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304261 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004262 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004263}
4264
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304265static float AmpToDb(float amplification)
4266{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304267 float db = DSD_VOLUME_MIN_DB;
4268 if (amplification > 0) {
4269 db = 20 * log10(amplification);
4270 if(db < DSD_VOLUME_MIN_DB)
4271 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304272 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304273 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304274}
4275
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004276static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4277 float right)
4278{
4279 struct stream_out *out = (struct stream_out *)stream;
4280 long volume = 0;
4281 char mixer_ctl_name[128] = "";
4282 struct audio_device *adev = out->dev;
4283 struct mixer_ctl *ctl = NULL;
4284 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4285 PCM_PLAYBACK);
4286
4287 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4288 "Playback %d Volume", pcm_device_id);
4289 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4290 if (!ctl) {
4291 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4292 __func__, mixer_ctl_name);
4293 return -EINVAL;
4294 }
4295 if (left != right)
4296 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4297 __func__, left, right);
4298 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4299 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4300 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4301 __func__, mixer_ctl_name, volume);
4302 return -EINVAL;
4303 }
4304 return 0;
4305}
4306
4307
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304308static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4309 float right)
4310{
4311 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304312 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304313 char mixer_ctl_name[128];
4314 struct audio_device *adev = out->dev;
4315 struct mixer_ctl *ctl;
4316 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4317 PCM_PLAYBACK);
4318
4319 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4320 "Compress Playback %d Volume", pcm_device_id);
4321 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4322 if (!ctl) {
4323 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4324 __func__, mixer_ctl_name);
4325 return -EINVAL;
4326 }
4327 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4328 __func__, mixer_ctl_name, left, right);
4329 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4330 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4331 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4332
4333 return 0;
4334}
4335
Zhou Song2b8f28f2017-09-11 10:51:38 +08004336static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4337 float right)
4338{
4339 struct stream_out *out = (struct stream_out *)stream;
4340 char mixer_ctl_name[] = "App Type Gain";
4341 struct audio_device *adev = out->dev;
4342 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304343 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004344
4345 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4346 if (!ctl) {
4347 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4348 __func__, mixer_ctl_name);
4349 return -EINVAL;
4350 }
4351
4352 set_values[0] = 0; //0: Rx Session 1:Tx Session
4353 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304354 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4355 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004356
4357 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4358 return 0;
4359}
4360
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004361static int out_set_volume(struct audio_stream_out *stream, float left,
4362 float right)
4363{
Eric Laurenta9024de2013-04-04 09:19:12 -07004364 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004365 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304366 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004367
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004368 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
4369
Eric Laurenta9024de2013-04-04 09:19:12 -07004370 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4371 /* only take left channel into account: the API is for stereo anyway */
4372 out->muted = (left == 0.0f);
4373 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004374 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304375 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004376 /*
4377 * Set mute or umute on HDMI passthrough stream.
4378 * Only take left channel into account.
4379 * Mute is 0 and unmute 1
4380 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304381 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304382 } else if (out->format == AUDIO_FORMAT_DSD){
4383 char mixer_ctl_name[128] = "DSD Volume";
4384 struct audio_device *adev = out->dev;
4385 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4386
4387 if (!ctl) {
4388 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4389 __func__, mixer_ctl_name);
4390 return -EINVAL;
4391 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304392 volume[0] = (long)(AmpToDb(left));
4393 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304394 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4395 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004396 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304397 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004398 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304399 if (!out->a2dp_compress_mute)
4400 ret = out_set_compr_volume(stream, left, right);
4401 out->volume_l = left;
4402 out->volume_r = right;
4403 pthread_mutex_unlock(&out->compr_mute_lock);
4404 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004405 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004406 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004407 if (!out->standby)
4408 ret = out_set_voip_volume(stream, left, right);
4409 out->volume_l = left;
4410 out->volume_r = right;
4411 return ret;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004412 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4413 ALOGV("%s: MMAP set volume called", __func__);
4414 if (!out->standby)
4415 ret = out_set_mmap_volume(stream, left, right);
4416 out->volume_l = left;
4417 out->volume_r = right;
4418 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004419 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004420
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004421 return -ENOSYS;
4422}
4423
Zhou Songc9672822017-08-16 16:01:39 +08004424static void update_frames_written(struct stream_out *out, size_t bytes)
4425{
4426 size_t bpf = 0;
4427
4428 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4429 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4430 bpf = 1;
4431 else if (!is_offload_usecase(out->usecase))
4432 bpf = audio_bytes_per_sample(out->format) *
4433 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004434
4435 pthread_mutex_lock(&out->position_query_lock);
4436 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004437 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004438 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4439 }
4440 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004441}
4442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004443static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4444 size_t bytes)
4445{
4446 struct stream_out *out = (struct stream_out *)stream;
4447 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004448 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304449 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004450 const size_t frame_size = audio_stream_out_frame_size(stream);
4451 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004452
Haynes Mathew George380745d2017-10-04 15:27:45 -07004453 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004454 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304455
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304456 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004457
Dhananjay Kumarac341582017-02-23 23:42:25 +05304458 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304459 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304460 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4461 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004462 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304463 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304464 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304465 ALOGD(" %s: sound card is not active/SSR state", __func__);
4466 ret= -EIO;
4467 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304468 }
4469 }
4470
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304471 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304472 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304473 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304474 goto exit;
4475 }
4476
Haynes Mathew George16081042017-05-31 17:16:49 -07004477 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4478 ret = -EINVAL;
4479 goto exit;
4480 }
4481
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304482 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4483 !out->is_iec61937_info_available) {
4484
4485 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4486 out->is_iec61937_info_available = true;
4487 } else if (audio_extn_passthru_is_enabled()) {
4488 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304489 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304490
4491 if((out->format == AUDIO_FORMAT_DTS) ||
4492 (out->format == AUDIO_FORMAT_DTS_HD)) {
4493 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4494 buffer, bytes);
4495 if (ret) {
4496 if (ret != -ENOSYS) {
4497 out->is_iec61937_info_available = false;
4498 ALOGD("iec61937 transmission info not yet updated retry");
4499 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304500 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304501 /* if stream has started and after that there is
4502 * stream config change (iec transmission config)
4503 * then trigger select_device to update backend configuration.
4504 */
4505 out->stream_config_changed = true;
4506 pthread_mutex_lock(&adev->lock);
4507 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304508 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4509 ret = -EINVAL;
4510 goto exit;
4511 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304512 pthread_mutex_unlock(&adev->lock);
4513 out->stream_config_changed = false;
4514 out->is_iec61937_info_available = true;
4515 }
4516 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304517
Garmond Leung317cbf12017-09-13 16:20:50 -07004518 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304519 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4520 (out->is_iec61937_info_available == true)) {
4521 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4522 ret = -EINVAL;
4523 goto exit;
4524 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304525 }
4526 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304527
4528 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4529 (audio_extn_a2dp_is_suspended())) {
4530 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4531 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304532 ret = -EIO;
4533 goto exit;
4534 }
4535 }
4536 }
4537
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004538 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004539 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004540 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004541 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4542 ret = voice_extn_compress_voip_start_output_stream(out);
4543 else
4544 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004545 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004546 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004547 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004548 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004549 goto exit;
4550 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304551 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004552 if (last_known_cal_step != -1) {
4553 ALOGD("%s: retry previous failed cal level set", __func__);
4554 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304555 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004556 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304557
4558 if ((out->is_iec61937_info_available == true) &&
4559 (audio_extn_passthru_is_passthrough_stream(out))&&
4560 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4561 ret = -EINVAL;
4562 goto exit;
4563 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004564 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004565
Ashish Jain81eb2a82015-05-13 10:52:34 +05304566 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004567 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304568 adev->is_channel_status_set = true;
4569 }
4570
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004571 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004572 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004573 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004574 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004575 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4576 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304577 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4578 ALOGD("copl(%p):send next track params in gapless", out);
4579 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4580 out->send_next_track_params = false;
4581 out->is_compr_metadata_avail = false;
4582 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004583 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304584 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304585 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004586
Ashish Jain83a6cc22016-06-28 14:34:17 +05304587 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304588 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304589 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304590 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004591 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304592 return -EINVAL;
4593 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304594 audio_format_t dst_format = out->hal_op_format;
4595 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304596
4597 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4598 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4599
Ashish Jain83a6cc22016-06-28 14:34:17 +05304600 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304601 dst_format,
4602 buffer,
4603 src_format,
4604 frames);
4605
Ashish Jain83a6cc22016-06-28 14:34:17 +05304606 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304607 bytes_to_write);
4608
4609 /*Convert written bytes in audio flinger format*/
4610 if (ret > 0)
4611 ret = ((ret * format_to_bitwidth_table[out->format]) /
4612 format_to_bitwidth_table[dst_format]);
4613 }
4614 } else
4615 ret = compress_write(out->compr, buffer, bytes);
4616
Zhou Songc9672822017-08-16 16:01:39 +08004617 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4618 update_frames_written(out, bytes);
4619
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304620 if (ret < 0)
4621 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08004622 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304623 /*msg to cb thread only if non blocking write is enabled*/
4624 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304625 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004626 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304627 } else if (-ENETRESET == ret) {
4628 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304629 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304630 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304631 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004632 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304633 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004634 }
Ashish Jain5106d362016-05-11 19:23:33 +05304635
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304636 /* Call compr start only when non-zero bytes of data is there to be rendered */
4637 if (!out->playback_started && ret > 0) {
4638 int status = compress_start(out->compr);
4639 if (status < 0) {
4640 ret = status;
4641 ALOGE("%s: compr start failed with err %d", __func__, errno);
4642 goto exit;
4643 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004644 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004645 out->playback_started = 1;
4646 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004647
4648 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4649 popcount(out->channel_mask),
4650 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004651 }
4652 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004653 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004654 return ret;
4655 } else {
4656 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004657 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004658 if (out->muted)
4659 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004660 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
4661 __func__, frames, frame_size, bytes_to_write);
4662
4663 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
4664 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4665 int16_t *src = (int16_t *)buffer;
4666 int16_t *dst = (int16_t *)buffer;
4667
4668 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
4669 out->format != AUDIO_FORMAT_PCM_16_BIT,
4670 "out_write called for incall music use case with wrong properties");
4671
4672 /*
4673 * FIXME: this can be removed once audio flinger mixer supports
4674 * mono output
4675 */
4676
4677 /*
4678 * Code below goes over each frame in the buffer and adds both
4679 * L and R samples and then divides by 2 to convert to mono
4680 */
4681 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
4682 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
4683 }
4684 bytes_to_write /= 2;
4685 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004686
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304687 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004688
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004689 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004690
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004691 if (out->config.rate)
4692 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4693 out->config.rate;
4694
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004695 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004696 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4697
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004698 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004699 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004700 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304701 out->convert_buffer != NULL) {
4702
4703 memcpy_by_audio_format(out->convert_buffer,
4704 out->hal_op_format,
4705 buffer,
4706 out->hal_ip_format,
4707 out->config.period_size * out->config.channels);
4708
4709 ret = pcm_write(out->pcm, out->convert_buffer,
4710 (out->config.period_size *
4711 out->config.channels *
4712 format_to_bitwidth_table[out->hal_op_format]));
4713 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304714 /*
4715 * To avoid underrun in DSP when the application is not pumping
4716 * data at required rate, check for the no. of bytes and ignore
4717 * pcm_write if it is less than actual buffer size.
4718 * It is a work around to a change in compress VOIP driver.
4719 */
4720 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4721 bytes < (out->config.period_size * out->config.channels *
4722 audio_bytes_per_sample(out->format))) {
4723 size_t voip_buf_size =
4724 out->config.period_size * out->config.channels *
4725 audio_bytes_per_sample(out->format);
4726 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4727 __func__, bytes, voip_buf_size);
4728 usleep(((uint64_t)voip_buf_size - bytes) *
4729 1000000 / audio_stream_out_frame_size(stream) /
4730 out_get_sample_rate(&out->stream.common));
4731 ret = 0;
4732 } else
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004733 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304734 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004735
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004736 release_out_focus(out);
4737
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304738 if (ret < 0)
4739 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004740 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304741 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004742 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004743 }
4744
4745exit:
Zhou Songc9672822017-08-16 16:01:39 +08004746 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304747 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304748 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304749 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004750 pthread_mutex_unlock(&out->lock);
4751
4752 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004753 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004754 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304755 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304756 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304757 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304758 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304759 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304760 out->standby = true;
4761 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304762 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304763 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4764 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4765 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004766
4767 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05304768 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004769 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004770 return ret;
4771 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004772 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004773 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004774 return bytes;
4775}
4776
4777static int out_get_render_position(const struct audio_stream_out *stream,
4778 uint32_t *dsp_frames)
4779{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004780 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004781
4782 if (dsp_frames == NULL)
4783 return -EINVAL;
4784
4785 *dsp_frames = 0;
4786 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004787 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304788
4789 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4790 * this operation and adev_close_output_stream(where out gets reset).
4791 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304792 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004793 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05304794 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004795 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304796 return 0;
4797 }
4798
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004799 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304800 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304801 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004802 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304803 if (ret < 0)
4804 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004805 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304806 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004807 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304808 if (-ENETRESET == ret) {
4809 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304810 out->card_status = CARD_STATUS_OFFLINE;
4811 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304812 } else if(ret < 0) {
4813 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304814 ret = -EINVAL;
4815 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304816 /*
4817 * Handle corner case where compress session is closed during SSR
4818 * and timestamp is queried
4819 */
4820 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304821 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304822 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304823 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004824 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05304825 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304826 pthread_mutex_unlock(&out->lock);
4827 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004828 } else if (audio_is_linear_pcm(out->format)) {
4829 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004830 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08004831 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004832 } else
4833 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004834}
4835
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004836static int out_add_audio_effect(const struct audio_stream *stream __unused,
4837 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004838{
4839 return 0;
4840}
4841
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004842static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4843 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004844{
4845 return 0;
4846}
4847
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004848static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4849 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004850{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304851 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004852}
4853
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004854static int out_get_presentation_position(const struct audio_stream_out *stream,
4855 uint64_t *frames, struct timespec *timestamp)
4856{
4857 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05304858 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07004859 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004860
Ashish Jain5106d362016-05-11 19:23:33 +05304861 /* below piece of code is not guarded against any lock because audioFliner serializes
4862 * this operation and adev_close_output_stream( where out gets reset).
4863 */
4864 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304865 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004866 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05304867 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4868 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4869 return 0;
4870 }
4871
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004872 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004873
Ashish Jain5106d362016-05-11 19:23:33 +05304874 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4875 ret = compress_get_tstamp(out->compr, &dsp_frames,
4876 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004877 // Adjustment accounts for A2dp encoder latency with offload usecases
4878 // Note: Encoder latency is returned in ms.
4879 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4880 unsigned long offset =
4881 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4882 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4883 }
Ashish Jain5106d362016-05-11 19:23:33 +05304884 ALOGVV("%s rendered frames %ld sample_rate %d",
4885 __func__, dsp_frames, out->sample_rate);
4886 *frames = dsp_frames;
4887 if (ret < 0)
4888 ret = -errno;
4889 if (-ENETRESET == ret) {
4890 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304891 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304892 ret = -EINVAL;
4893 } else
4894 ret = 0;
4895 /* this is the best we can do */
4896 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07004897 } else {
4898 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08004899 unsigned int avail;
4900 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
4901 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
4902 int64_t signed_frames = out->written - kernel_buffer_size + avail;
4903 // This adjustment accounts for buffering after app processor.
4904 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07004905 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08004906 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07004907
Weiyin Jiangd4633762018-03-16 12:05:03 +08004908 // Adjustment accounts for A2dp encoder latency with non offload usecases
4909 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
4910 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4911 signed_frames -=
4912 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4913 }
4914
4915 // It would be unusual for this value to be negative, but check just in case ...
4916 if (signed_frames >= 0) {
4917 *frames = signed_frames;
4918 ret = 0;
4919 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004920 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304921 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304922 *frames = out->written;
4923 clock_gettime(CLOCK_MONOTONIC, timestamp);
4924 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004925 }
4926 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004927 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004928 return ret;
4929}
4930
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004931static int out_set_callback(struct audio_stream_out *stream,
4932 stream_callback_t callback, void *cookie)
4933{
4934 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004935 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004936
4937 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004938 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004939 out->client_callback = callback;
4940 out->client_cookie = cookie;
4941 if (out->adsp_hdlr_stream_handle) {
4942 ret = audio_extn_adsp_hdlr_stream_set_callback(
4943 out->adsp_hdlr_stream_handle,
4944 callback,
4945 cookie);
4946 if (ret)
4947 ALOGW("%s:adsp hdlr callback registration failed %d",
4948 __func__, ret);
4949 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004950 pthread_mutex_unlock(&out->lock);
4951 return 0;
4952}
4953
4954static int out_pause(struct audio_stream_out* stream)
4955{
4956 struct stream_out *out = (struct stream_out *)stream;
4957 int status = -ENOSYS;
4958 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004959 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004960 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004961 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004962 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304963 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304964 status = compress_pause(out->compr);
4965
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004966 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004967
Mingming Yin21854652016-04-13 11:54:02 -07004968 if (audio_extn_passthru_is_active()) {
4969 ALOGV("offload use case, pause passthru");
4970 audio_extn_passthru_on_pause(out);
4971 }
4972
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304973 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004974 audio_extn_dts_notify_playback_state(out->usecase, 0,
4975 out->sample_rate, popcount(out->channel_mask),
4976 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004977 }
4978 pthread_mutex_unlock(&out->lock);
4979 }
4980 return status;
4981}
4982
4983static int out_resume(struct audio_stream_out* stream)
4984{
4985 struct stream_out *out = (struct stream_out *)stream;
4986 int status = -ENOSYS;
4987 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004988 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004989 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004990 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004991 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004992 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304993 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304994 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004995 }
4996 if (!status) {
4997 out->offload_state = OFFLOAD_STATE_PLAYING;
4998 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304999 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005000 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5001 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005002 }
5003 pthread_mutex_unlock(&out->lock);
5004 }
5005 return status;
5006}
5007
5008static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5009{
5010 struct stream_out *out = (struct stream_out *)stream;
5011 int status = -ENOSYS;
5012 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005013 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005014 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005015 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5016 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5017 else
5018 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5019 pthread_mutex_unlock(&out->lock);
5020 }
5021 return status;
5022}
5023
5024static int out_flush(struct audio_stream_out* stream)
5025{
5026 struct stream_out *out = (struct stream_out *)stream;
5027 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005028 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005029 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005030 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005031 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5032 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005033 } else {
5034 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5035 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005036 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005037 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005038 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005039 return 0;
5040 }
5041 return -ENOSYS;
5042}
5043
Haynes Mathew George16081042017-05-31 17:16:49 -07005044static int out_stop(const struct audio_stream_out* stream)
5045{
5046 struct stream_out *out = (struct stream_out *)stream;
5047 struct audio_device *adev = out->dev;
5048 int ret = -ENOSYS;
5049
5050 ALOGV("%s", __func__);
5051 pthread_mutex_lock(&adev->lock);
5052 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5053 out->playback_started && out->pcm != NULL) {
5054 pcm_stop(out->pcm);
5055 ret = stop_output_stream(out);
5056 out->playback_started = false;
5057 }
5058 pthread_mutex_unlock(&adev->lock);
5059 return ret;
5060}
5061
5062static int out_start(const struct audio_stream_out* stream)
5063{
5064 struct stream_out *out = (struct stream_out *)stream;
5065 struct audio_device *adev = out->dev;
5066 int ret = -ENOSYS;
5067
5068 ALOGV("%s", __func__);
5069 pthread_mutex_lock(&adev->lock);
5070 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5071 !out->playback_started && out->pcm != NULL) {
5072 ret = start_output_stream(out);
5073 if (ret == 0) {
5074 out->playback_started = true;
5075 }
5076 }
5077 pthread_mutex_unlock(&adev->lock);
5078 return ret;
5079}
5080
5081/*
5082 * Modify config->period_count based on min_size_frames
5083 */
5084static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5085{
5086 int periodCountRequested = (min_size_frames + config->period_size - 1)
5087 / config->period_size;
5088 int periodCount = MMAP_PERIOD_COUNT_MIN;
5089
5090 ALOGV("%s original config.period_size = %d config.period_count = %d",
5091 __func__, config->period_size, config->period_count);
5092
5093 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5094 periodCount *= 2;
5095 }
5096 config->period_count = periodCount;
5097
5098 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5099}
5100
5101static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5102 int32_t min_size_frames,
5103 struct audio_mmap_buffer_info *info)
5104{
5105 struct stream_out *out = (struct stream_out *)stream;
5106 struct audio_device *adev = out->dev;
5107 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005108 unsigned int offset1 = 0;
5109 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005110 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005111 uint32_t mmap_size;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005112 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005113
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005114 ALOGD("%s", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07005115 pthread_mutex_lock(&adev->lock);
5116
5117 if (info == NULL || min_size_frames == 0) {
5118 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5119 ret = -EINVAL;
5120 goto exit;
5121 }
5122 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5123 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5124 ret = -ENOSYS;
5125 goto exit;
5126 }
5127 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5128 if (out->pcm_device_id < 0) {
5129 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5130 __func__, out->pcm_device_id, out->usecase);
5131 ret = -EINVAL;
5132 goto exit;
5133 }
5134
5135 adjust_mmap_period_count(&out->config, min_size_frames);
5136
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005137 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005138 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5139 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5140 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
5141 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5142 step = "open";
5143 ret = -ENODEV;
5144 goto exit;
5145 }
5146 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5147 if (ret < 0) {
5148 step = "begin";
5149 goto exit;
5150 }
5151 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005152 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005153 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005154 ret = platform_get_mmap_data_fd(adev->platform,
5155 out->pcm_device_id, 0 /*playback*/,
5156 &info->shared_memory_fd,
5157 &mmap_size);
5158 if (ret < 0) {
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005159 // Fall back to non exclusive mode
5160 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5161 } else {
5162 if (mmap_size < buffer_size) {
5163 step = "mmap";
5164 goto exit;
5165 }
5166 // FIXME: indicate exclusive mode support by returning a negative buffer size
5167 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005168 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005169 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07005170
5171 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5172 if (ret < 0) {
5173 step = "commit";
5174 goto exit;
5175 }
5176
5177 out->standby = false;
5178 ret = 0;
5179
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005180 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005181 __func__, info->shared_memory_address, info->buffer_size_frames);
5182
5183exit:
5184 if (ret != 0) {
5185 if (out->pcm == NULL) {
5186 ALOGE("%s: %s - %d", __func__, step, ret);
5187 } else {
5188 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5189 pcm_close(out->pcm);
5190 out->pcm = NULL;
5191 }
5192 }
5193 pthread_mutex_unlock(&adev->lock);
5194 return ret;
5195}
5196
5197static int out_get_mmap_position(const struct audio_stream_out *stream,
5198 struct audio_mmap_position *position)
5199{
5200 struct stream_out *out = (struct stream_out *)stream;
5201 ALOGVV("%s", __func__);
5202 if (position == NULL) {
5203 return -EINVAL;
5204 }
5205 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005206 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005207 return -ENOSYS;
5208 }
5209 if (out->pcm == NULL) {
5210 return -ENOSYS;
5211 }
5212
5213 struct timespec ts = { 0, 0 };
5214 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5215 if (ret < 0) {
5216 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5217 return ret;
5218 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005219 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005220 return 0;
5221}
5222
5223
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005224/** audio_stream_in implementation **/
5225static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5226{
5227 struct stream_in *in = (struct stream_in *)stream;
5228
5229 return in->config.rate;
5230}
5231
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005232static int in_set_sample_rate(struct audio_stream *stream __unused,
5233 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005234{
5235 return -ENOSYS;
5236}
5237
5238static size_t in_get_buffer_size(const struct audio_stream *stream)
5239{
5240 struct stream_in *in = (struct stream_in *)stream;
5241
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005242 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5243 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005244 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5245 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 -07005246 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5247 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305248 else if(audio_extn_cin_attached_usecase(in->usecase))
5249 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005250
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005251 return in->config.period_size * in->af_period_multiplier *
5252 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005253}
5254
5255static uint32_t in_get_channels(const struct audio_stream *stream)
5256{
5257 struct stream_in *in = (struct stream_in *)stream;
5258
5259 return in->channel_mask;
5260}
5261
5262static audio_format_t in_get_format(const struct audio_stream *stream)
5263{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005264 struct stream_in *in = (struct stream_in *)stream;
5265
5266 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005267}
5268
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005269static int in_set_format(struct audio_stream *stream __unused,
5270 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005271{
5272 return -ENOSYS;
5273}
5274
5275static int in_standby(struct audio_stream *stream)
5276{
5277 struct stream_in *in = (struct stream_in *)stream;
5278 struct audio_device *adev = in->dev;
5279 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305280 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5281 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005282 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305283
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005284 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005285 if (!in->standby && in->is_st_session) {
5286 ALOGD("%s: sound trigger pcm stop lab", __func__);
5287 audio_extn_sound_trigger_stop_lab(in);
5288 in->standby = 1;
5289 }
5290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005291 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005292 if (adev->adm_deregister_stream)
5293 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5294
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005295 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005296 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005297 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005298 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005299 voice_extn_compress_voip_close_input_stream(stream);
5300 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005301 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5302 do_stop = in->capture_started;
5303 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005304 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305305 if (audio_extn_cin_attached_usecase(in->usecase))
5306 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005307 }
5308
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005309 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005310 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005311 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005312 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005313 in->pcm = NULL;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005314 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005315
5316 if (do_stop)
5317 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005318 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005319 }
5320 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005321 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005322 return status;
5323}
5324
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005325static int in_dump(const struct audio_stream *stream __unused,
5326 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005327{
5328 return 0;
5329}
5330
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305331static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5332{
5333 if (!stream || !parms)
5334 return;
5335
5336 struct stream_in *in = (struct stream_in *)stream;
5337 struct audio_device *adev = in->dev;
5338
5339 card_status_t status;
5340 int card;
5341 if (parse_snd_card_status(parms, &card, &status) < 0)
5342 return;
5343
5344 pthread_mutex_lock(&adev->lock);
5345 bool valid_cb = (card == adev->snd_card);
5346 pthread_mutex_unlock(&adev->lock);
5347
5348 if (!valid_cb)
5349 return;
5350
5351 lock_input_stream(in);
5352 if (in->card_status != status)
5353 in->card_status = status;
5354 pthread_mutex_unlock(&in->lock);
5355
5356 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5357 use_case_table[in->usecase],
5358 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5359
5360 // a better solution would be to report error back to AF and let
5361 // it put the stream to standby
5362 if (status == CARD_STATUS_OFFLINE)
5363 in_standby(&in->stream.common);
5364
5365 return;
5366}
5367
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005368static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5369{
5370 struct stream_in *in = (struct stream_in *)stream;
5371 struct audio_device *adev = in->dev;
5372 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005373 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005374 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005375
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305376 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005377 parms = str_parms_create_str(kvpairs);
5378
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305379 if (!parms)
5380 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005381 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005382 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005383
5384 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5385 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005386 val = atoi(value);
5387 /* no audio source uses val == 0 */
5388 if ((in->source != val) && (val != 0)) {
5389 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005390 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5391 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5392 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005393 (in->config.rate == 8000 || in->config.rate == 16000 ||
5394 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005395 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005396 err = voice_extn_compress_voip_open_input_stream(in);
5397 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005398 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005399 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005400 }
5401 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005402 }
5403 }
5404
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005405 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5406 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005407 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005408 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5409
5410 // Workaround: If routing to an non existing usb device, fail gracefully
5411 // The routing request will otherwise block during 10 second
5412 int card;
5413 if (audio_is_usb_in_device(val) &&
5414 (card = get_alive_usb_card(parms)) >= 0) {
5415
5416 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5417 ret = -ENOSYS;
5418 } else {
5419
5420 in->device = val;
5421 /* If recording is in progress, change the tx device to new device */
5422 if (!in->standby && !in->is_st_session) {
5423 ALOGV("update input routing change");
5424 // inform adm before actual routing to prevent glitches.
5425 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005426 adev->adm_on_routing_change(adev->adm_data,
5427 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005428 ret = select_devices(adev, in->usecase);
5429 }
5430 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005431 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005432 }
5433 }
5434
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305435 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5436 if (err >= 0) {
5437 strlcpy(in->profile, value, sizeof(in->profile));
5438 ALOGV("updating stream profile with value '%s'", in->profile);
5439 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5440 &adev->streams_input_cfg_list,
5441 in->device, in->flags, in->format,
5442 in->sample_rate, in->bit_width,
5443 in->profile, &in->app_type_cfg);
5444 }
5445
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005446 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005447 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005448
5449 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305450error:
Eric Laurent994a6932013-07-17 11:51:42 -07005451 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005452 return ret;
5453}
5454
5455static char* in_get_parameters(const struct audio_stream *stream,
5456 const char *keys)
5457{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005458 struct stream_in *in = (struct stream_in *)stream;
5459 struct str_parms *query = str_parms_create_str(keys);
5460 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005461 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005462
5463 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005464 if (reply) {
5465 str_parms_destroy(reply);
5466 }
5467 if (query) {
5468 str_parms_destroy(query);
5469 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005470 ALOGE("in_get_parameters: failed to create query or reply");
5471 return NULL;
5472 }
5473
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005474 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005475
5476 voice_extn_in_get_parameters(in, query, reply);
5477
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005478 stream_get_parameter_channels(query, reply,
5479 &in->supported_channel_masks[0]);
5480 stream_get_parameter_formats(query, reply,
5481 &in->supported_formats[0]);
5482 stream_get_parameter_rates(query, reply,
5483 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005484 str = str_parms_to_str(reply);
5485 str_parms_destroy(query);
5486 str_parms_destroy(reply);
5487
5488 ALOGV("%s: exit: returns - %s", __func__, str);
5489 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005490}
5491
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005492static int in_set_gain(struct audio_stream_in *stream __unused,
5493 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005494{
5495 return 0;
5496}
5497
5498static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5499 size_t bytes)
5500{
5501 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305502
5503 if (in == NULL) {
5504 ALOGE("%s: stream_in ptr is NULL", __func__);
5505 return -EINVAL;
5506 }
5507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005508 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305509 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305510 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005511
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005512 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305513
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005514 if (in->is_st_session) {
5515 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5516 /* Read from sound trigger HAL */
5517 audio_extn_sound_trigger_read(in, buffer, bytes);
5518 pthread_mutex_unlock(&in->lock);
5519 return bytes;
5520 }
5521
Haynes Mathew George16081042017-05-31 17:16:49 -07005522 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5523 ret = -ENOSYS;
5524 goto exit;
5525 }
5526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005527 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005528 pthread_mutex_lock(&adev->lock);
5529 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5530 ret = voice_extn_compress_voip_start_input_stream(in);
5531 else
5532 ret = start_input_stream(in);
5533 pthread_mutex_unlock(&adev->lock);
5534 if (ret != 0) {
5535 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005536 }
5537 in->standby = 0;
5538 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005539
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005540 // what's the duration requested by the client?
5541 long ns = 0;
5542
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305543 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005544 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5545 in->config.rate;
5546
5547 request_in_focus(in, ns);
5548 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005549
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305550 if (audio_extn_cin_attached_usecase(in->usecase)) {
5551 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5552 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305553 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005554 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305555 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005556 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005557 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005558 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005559 } else if (audio_extn_ffv_get_stream() == in) {
5560 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305561 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005562 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305563 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5564 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5565 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5566 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305567 ret = -EINVAL;
5568 goto exit;
5569 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305570 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305571 ret = -errno;
5572 }
5573 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305574 /* bytes read is always set to bytes for non compress usecases */
5575 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005576 }
5577
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005578 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005579
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005580 /*
5581 * Instead of writing zeroes here, we could trust the hardware
5582 * to always provide zeroes when muted.
5583 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305584 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5585 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005586 memset(buffer, 0, bytes);
5587
5588exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005589 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305590 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005591 pthread_mutex_unlock(&in->lock);
5592
5593 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305594 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305595 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305596 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305597 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305598 in->standby = true;
5599 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305600 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5601 bytes_read = bytes;
5602 memset(buffer, 0, bytes);
5603 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005604 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005605 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305606 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305607 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005608 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305609 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005610}
5611
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005612static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005613{
5614 return 0;
5615}
5616
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005617static int add_remove_audio_effect(const struct audio_stream *stream,
5618 effect_handle_t effect,
5619 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005620{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005621 struct stream_in *in = (struct stream_in *)stream;
5622 int status = 0;
5623 effect_descriptor_t desc;
5624
5625 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005626 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5627
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005628 if (status != 0)
5629 return status;
5630
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005631 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005632 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08005633 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5634 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005635 in->enable_aec != enable &&
5636 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5637 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005638 if (!in->standby) {
5639 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5640 select_devices(in->dev, in->usecase);
5641 }
5642
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005643 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005644 if (in->enable_ns != enable &&
5645 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5646 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005647 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08005648 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5649 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005650 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5651 select_devices(in->dev, in->usecase);
5652 } else
5653 select_devices(in->dev, in->usecase);
5654 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005655 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005656 pthread_mutex_unlock(&in->dev->lock);
5657 pthread_mutex_unlock(&in->lock);
5658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005659 return 0;
5660}
5661
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005662static int in_add_audio_effect(const struct audio_stream *stream,
5663 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005664{
Eric Laurent994a6932013-07-17 11:51:42 -07005665 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005666 return add_remove_audio_effect(stream, effect, true);
5667}
5668
5669static int in_remove_audio_effect(const struct audio_stream *stream,
5670 effect_handle_t effect)
5671{
Eric Laurent994a6932013-07-17 11:51:42 -07005672 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005673 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005674}
5675
Haynes Mathew George16081042017-05-31 17:16:49 -07005676static int in_stop(const struct audio_stream_in* stream)
5677{
5678 struct stream_in *in = (struct stream_in *)stream;
5679 struct audio_device *adev = in->dev;
5680
5681 int ret = -ENOSYS;
5682 ALOGV("%s", __func__);
5683 pthread_mutex_lock(&adev->lock);
5684 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5685 in->capture_started && in->pcm != NULL) {
5686 pcm_stop(in->pcm);
5687 ret = stop_input_stream(in);
5688 in->capture_started = false;
5689 }
5690 pthread_mutex_unlock(&adev->lock);
5691 return ret;
5692}
5693
5694static int in_start(const struct audio_stream_in* stream)
5695{
5696 struct stream_in *in = (struct stream_in *)stream;
5697 struct audio_device *adev = in->dev;
5698 int ret = -ENOSYS;
5699
5700 ALOGV("%s in %p", __func__, in);
5701 pthread_mutex_lock(&adev->lock);
5702 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5703 !in->capture_started && in->pcm != NULL) {
5704 if (!in->capture_started) {
5705 ret = start_input_stream(in);
5706 if (ret == 0) {
5707 in->capture_started = true;
5708 }
5709 }
5710 }
5711 pthread_mutex_unlock(&adev->lock);
5712 return ret;
5713}
5714
5715static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5716 int32_t min_size_frames,
5717 struct audio_mmap_buffer_info *info)
5718{
5719 struct stream_in *in = (struct stream_in *)stream;
5720 struct audio_device *adev = in->dev;
5721 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005722 unsigned int offset1 = 0;
5723 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005724 const char *step = "";
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005725 uint32_t mmap_size = 0;
5726 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005727
5728 pthread_mutex_lock(&adev->lock);
5729 ALOGV("%s in %p", __func__, in);
5730
5731 if (info == NULL || min_size_frames == 0) {
5732 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5733 ret = -EINVAL;
5734 goto exit;
5735 }
5736 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5737 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5738 ALOGV("%s in %p", __func__, in);
5739 ret = -ENOSYS;
5740 goto exit;
5741 }
5742 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5743 if (in->pcm_device_id < 0) {
5744 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5745 __func__, in->pcm_device_id, in->usecase);
5746 ret = -EINVAL;
5747 goto exit;
5748 }
5749
5750 adjust_mmap_period_count(&in->config, min_size_frames);
5751
5752 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5753 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5754 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5755 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
5756 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5757 step = "open";
5758 ret = -ENODEV;
5759 goto exit;
5760 }
5761
5762 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5763 if (ret < 0) {
5764 step = "begin";
5765 goto exit;
5766 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005767
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005768 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5769 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
5770 info->burst_size_frames = in->config.period_size;
5771 ret = platform_get_mmap_data_fd(adev->platform,
5772 in->pcm_device_id, 1 /*capture*/,
5773 &info->shared_memory_fd,
5774 &mmap_size);
5775 if (ret < 0) {
5776 // Fall back to non exclusive mode
5777 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
5778 } else {
5779 if (mmap_size < buffer_size) {
5780 step = "mmap";
5781 goto exit;
5782 }
5783 // FIXME: indicate exclusive mode support by returning a negative buffer size
5784 info->buffer_size_frames *= -1;
5785 }
5786
5787 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07005788
5789 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
5790 if (ret < 0) {
5791 step = "commit";
5792 goto exit;
5793 }
5794
5795 in->standby = false;
5796 ret = 0;
5797
5798 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5799 __func__, info->shared_memory_address, info->buffer_size_frames);
5800
5801exit:
5802 if (ret != 0) {
5803 if (in->pcm == NULL) {
5804 ALOGE("%s: %s - %d", __func__, step, ret);
5805 } else {
5806 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
5807 pcm_close(in->pcm);
5808 in->pcm = NULL;
5809 }
5810 }
5811 pthread_mutex_unlock(&adev->lock);
5812 return ret;
5813}
5814
5815static int in_get_mmap_position(const struct audio_stream_in *stream,
5816 struct audio_mmap_position *position)
5817{
5818 struct stream_in *in = (struct stream_in *)stream;
5819 ALOGVV("%s", __func__);
5820 if (position == NULL) {
5821 return -EINVAL;
5822 }
5823 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
5824 return -ENOSYS;
5825 }
5826 if (in->pcm == NULL) {
5827 return -ENOSYS;
5828 }
5829 struct timespec ts = { 0, 0 };
5830 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
5831 if (ret < 0) {
5832 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
5833 return ret;
5834 }
5835 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
5836 return 0;
5837}
5838
Naresh Tannirudcb47c52018-06-25 16:23:32 +05305839static int in_get_active_microphones(const struct audio_stream_in *stream,
5840 struct audio_microphone_characteristic_t *mic_array,
5841 size_t *mic_count) {
5842 struct stream_in *in = (struct stream_in *)stream;
5843 struct audio_device *adev = in->dev;
5844 ALOGVV("%s", __func__);
5845
5846 lock_input_stream(in);
5847 pthread_mutex_lock(&adev->lock);
5848 int ret = platform_get_active_microphones(adev->platform,
5849 audio_channel_count_from_in_mask(in->channel_mask),
5850 in->usecase, mic_array, mic_count);
5851 pthread_mutex_unlock(&adev->lock);
5852 pthread_mutex_unlock(&in->lock);
5853
5854 return ret;
5855}
5856
5857static int adev_get_microphones(const struct audio_hw_device *dev,
5858 struct audio_microphone_characteristic_t *mic_array,
5859 size_t *mic_count) {
5860 struct audio_device *adev = (struct audio_device *)dev;
5861 ALOGVV("%s", __func__);
5862
5863 pthread_mutex_lock(&adev->lock);
5864 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
5865 pthread_mutex_unlock(&adev->lock);
5866
5867 return ret;
5868}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305869int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07005870 audio_io_handle_t handle,
5871 audio_devices_t devices,
5872 audio_output_flags_t flags,
5873 struct audio_config *config,
5874 struct audio_stream_out **stream_out,
5875 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005876{
5877 struct audio_device *adev = (struct audio_device *)dev;
5878 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305879 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005880 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005881 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05305882 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005883 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
5884 bool is_usb_dev = audio_is_usb_out_device(devices) &&
5885 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
5886 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005887
kunleizdff872d2018-08-20 14:40:33 +08005888 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08005889 is_usb_dev = false;
5890 devices = AUDIO_DEVICE_OUT_SPEAKER;
5891 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
5892 __func__, devices);
5893 }
5894
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005895 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005897 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
5898
Mingming Yin3a941d42016-02-17 18:08:05 -08005899 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
5900 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305901 devices, flags, &out->stream);
5902
5903
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005904 if (!out) {
5905 return -ENOMEM;
5906 }
5907
Haynes Mathew George204045b2015-02-25 20:32:03 -08005908 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005909 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305910 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08005911 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08005912 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5913
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005914 if (devices == AUDIO_DEVICE_NONE)
5915 devices = AUDIO_DEVICE_OUT_SPEAKER;
5916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005917 out->flags = flags;
5918 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07005919 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07005920 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005921 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05305922 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05305923 if (out->channel_mask == AUDIO_CHANNEL_NONE)
5924 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
5925 else
5926 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07005927 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005928 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08005929 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305930 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305931 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305932 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005933 out->hal_output_suspend_supported = 0;
5934 out->dynamic_pm_qos_config_supported = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005935
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05305936 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05305937 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07005938 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
5939
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005940 if (audio_is_linear_pcm(out->format) &&
5941 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
5942 pthread_mutex_lock(&adev->lock);
5943 if (is_hdmi) {
5944 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
5945 ret = read_hdmi_sink_caps(out);
5946 } else if (is_usb_dev) {
5947 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
5948 &config->format,
5949 &out->supported_formats[0],
5950 MAX_SUPPORTED_FORMATS,
5951 &config->channel_mask,
5952 &out->supported_channel_masks[0],
5953 MAX_SUPPORTED_CHANNEL_MASKS,
5954 &config->sample_rate,
5955 &out->supported_sample_rates[0],
5956 MAX_SUPPORTED_SAMPLE_RATES);
5957 ALOGV("plugged dev USB ret %d", ret);
5958 } else {
5959 ret = -1;
5960 }
5961 pthread_mutex_unlock(&adev->lock);
5962 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005963 if (ret == -ENOSYS) {
5964 /* ignore and go with default */
5965 ret = 0;
5966 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005967 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08005968 goto error_open;
5969 }
5970 }
5971 }
5972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005973 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07005974#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005975 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5976 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
5977 out->sample_rate == 32000 || out->sample_rate == 48000)) {
5978 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
5979 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
5980 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5981
5982 out->config = default_pcm_config_voip_copp;
5983 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5984 out->config.rate = out->sample_rate;
5985
5986#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05305987 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005988 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08005989 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005990 ret = voice_extn_compress_voip_open_output_stream(out);
5991 if (ret != 0) {
5992 ALOGE("%s: Compress voip output cannot be opened, error:%d",
5993 __func__, ret);
5994 goto error_open;
5995 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005996#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005997 } else if (audio_is_linear_pcm(out->format) &&
5998 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
5999 out->channel_mask = config->channel_mask;
6000 out->sample_rate = config->sample_rate;
6001 out->format = config->format;
6002 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6003 // does this change?
6004 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6005 out->config.rate = config->sample_rate;
6006 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6007 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6008 audio_bytes_per_sample(config->format));
6009 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006010 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306011 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306012 pthread_mutex_lock(&adev->lock);
6013 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6014 pthread_mutex_unlock(&adev->lock);
6015
6016 // reject offload during card offline to allow
6017 // fallback to s/w paths
6018 if (offline) {
6019 ret = -ENODEV;
6020 goto error_open;
6021 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006022
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006023 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6024 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6025 ALOGE("%s: Unsupported Offload information", __func__);
6026 ret = -EINVAL;
6027 goto error_open;
6028 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006029
Atul Khare3fa6e542017-08-09 00:56:17 +05306030 if (config->offload_info.format == 0)
6031 config->offload_info.format = config->format;
6032 if (config->offload_info.sample_rate == 0)
6033 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006034
Mingming Yin90310102013-11-13 16:57:00 -08006035 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306036 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006037 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006038 ret = -EINVAL;
6039 goto error_open;
6040 }
6041
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006042 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6043 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6044 (audio_extn_passthru_is_passthrough_stream(out)) &&
6045 !((config->sample_rate == 48000) ||
6046 (config->sample_rate == 96000) ||
6047 (config->sample_rate == 192000))) {
6048 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6049 __func__, config->sample_rate, config->offload_info.format);
6050 ret = -EINVAL;
6051 goto error_open;
6052 }
6053
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006054 out->compr_config.codec = (struct snd_codec *)
6055 calloc(1, sizeof(struct snd_codec));
6056
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006057 if (!out->compr_config.codec) {
6058 ret = -ENOMEM;
6059 goto error_open;
6060 }
6061
Dhananjay Kumarac341582017-02-23 23:42:25 +05306062 out->stream.pause = out_pause;
6063 out->stream.resume = out_resume;
6064 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306065 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306066 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006067 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306068 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006069 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306070 } else {
6071 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6072 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006073 }
vivek mehta446c3962015-09-14 10:57:35 -07006074
6075 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006076 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6077 config->format == 0 && config->sample_rate == 0 &&
6078 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006079 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006080 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6081 } else {
6082 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6083 ret = -EEXIST;
6084 goto error_open;
6085 }
vivek mehta446c3962015-09-14 10:57:35 -07006086 }
6087
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006088 if (config->offload_info.channel_mask)
6089 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006090 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006091 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006092 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006093 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306094 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006095 ret = -EINVAL;
6096 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006097 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006098
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006099 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006100 out->sample_rate = config->offload_info.sample_rate;
6101
Mingming Yin3ee55c62014-08-04 14:23:35 -07006102 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006103
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306104 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306105 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306106 audio_extn_dolby_send_ddp_endp_params(adev);
6107 audio_extn_dolby_set_dmid(adev);
6108 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006109
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006110 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006111 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006112 out->compr_config.codec->bit_rate =
6113 config->offload_info.bit_rate;
6114 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306115 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006116 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306117 /* Update bit width only for non passthrough usecases.
6118 * For passthrough usecases, the output will always be opened @16 bit
6119 */
6120 if (!audio_extn_passthru_is_passthrough_stream(out))
6121 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306122
6123 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6124 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6125 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6126
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006127 /*TODO: Do we need to change it for passthrough */
6128 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006129
Manish Dewangana6fc5442015-08-24 20:30:31 +05306130 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6131 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306132 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306133 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306134 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6135 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306136
6137 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6138 AUDIO_FORMAT_PCM) {
6139
6140 /*Based on platform support, configure appropriate alsa format for corresponding
6141 *hal input format.
6142 */
6143 out->compr_config.codec->format = hal_format_to_alsa(
6144 config->offload_info.format);
6145
Ashish Jain83a6cc22016-06-28 14:34:17 +05306146 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306147 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306148 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306149
Dhananjay Kumarac341582017-02-23 23:42:25 +05306150 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306151 *hal input format and alsa format might differ based on platform support.
6152 */
6153 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306154 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306155
6156 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6157
6158 /* Check if alsa session is configured with the same format as HAL input format,
6159 * if not then derive correct fragment size needed to accomodate the
6160 * conversion of HAL input format to alsa format.
6161 */
6162 audio_extn_utils_update_direct_pcm_fragment_size(out);
6163
6164 /*if hal input and output fragment size is different this indicates HAL input format is
6165 *not same as the alsa format
6166 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306167 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306168 /*Allocate a buffer to convert input data to the alsa configured format.
6169 *size of convert buffer is equal to the size required to hold one fragment size
6170 *worth of pcm data, this is because flinger does not write more than fragment_size
6171 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306172 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6173 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306174 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6175 ret = -ENOMEM;
6176 goto error_open;
6177 }
6178 }
6179 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6180 out->compr_config.fragment_size =
6181 audio_extn_passthru_get_buffer_size(&config->offload_info);
6182 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6183 } else {
6184 out->compr_config.fragment_size =
6185 platform_get_compress_offload_buffer_size(&config->offload_info);
6186 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6187 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006188
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306189 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6190 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6191 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006192 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306193 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006194
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306195 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6196 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6197 }
6198
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006199 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6200 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006201
Manish Dewangan69426c82017-01-30 17:35:36 +05306202 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6203 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6204 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6205 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6206 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6207 } else {
6208 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6209 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006210
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306211 memset(&out->channel_map_param, 0,
6212 sizeof(struct audio_out_channel_map_param));
6213
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006214 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306215 out->send_next_track_params = false;
6216 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006217 out->offload_state = OFFLOAD_STATE_IDLE;
6218 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006219 out->writeAt.tv_sec = 0;
6220 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006221
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006222 audio_extn_dts_create_state_notifier_node(out->usecase);
6223
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006224 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6225 __func__, config->offload_info.version,
6226 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306227
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306228 /* Check if DSD audio format is supported in codec
6229 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306230 */
6231
6232 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306233 (!platform_check_codec_dsd_support(adev->platform) ||
6234 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306235 ret = -EINVAL;
6236 goto error_open;
6237 }
6238
Ashish Jain5106d362016-05-11 19:23:33 +05306239 /* Disable gapless if any of the following is true
6240 * passthrough playback
6241 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306242 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306243 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306244 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306245 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006246 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306247 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306248 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306249 check_and_set_gapless_mode(adev, false);
6250 } else
6251 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006252
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306253 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006254 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6255 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306256 if (config->format == AUDIO_FORMAT_DSD) {
6257 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6258 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6259 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006260
6261 create_offload_callback_thread(out);
6262
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006263 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006264 switch (config->sample_rate) {
6265 case 0:
6266 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6267 break;
6268 case 8000:
6269 case 16000:
6270 case 48000:
6271 out->sample_rate = config->sample_rate;
6272 break;
6273 default:
6274 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
6275 config->sample_rate);
6276 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6277 ret = -EINVAL;
6278 goto error_open;
6279 }
6280 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6281 switch (config->channel_mask) {
6282 case AUDIO_CHANNEL_NONE:
6283 case AUDIO_CHANNEL_OUT_STEREO:
6284 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6285 break;
6286 default:
6287 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
6288 config->channel_mask);
6289 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6290 ret = -EINVAL;
6291 goto error_open;
6292 }
6293 switch (config->format) {
6294 case AUDIO_FORMAT_DEFAULT:
6295 case AUDIO_FORMAT_PCM_16_BIT:
6296 out->format = AUDIO_FORMAT_PCM_16_BIT;
6297 break;
6298 default:
6299 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
6300 config->format);
6301 config->format = AUDIO_FORMAT_PCM_16_BIT;
6302 ret = -EINVAL;
6303 goto error_open;
6304 }
6305
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306306 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006307 if (ret != 0) {
6308 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006309 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006310 goto error_open;
6311 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006312 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006313 if (config->sample_rate == 0)
6314 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6315 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6316 config->sample_rate != 8000) {
6317 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6318 ret = -EINVAL;
6319 goto error_open;
6320 }
6321 out->sample_rate = config->sample_rate;
6322 out->config.rate = config->sample_rate;
6323 if (config->format == AUDIO_FORMAT_DEFAULT)
6324 config->format = AUDIO_FORMAT_PCM_16_BIT;
6325 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6326 config->format = AUDIO_FORMAT_PCM_16_BIT;
6327 ret = -EINVAL;
6328 goto error_open;
6329 }
6330 out->format = config->format;
6331 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
6332 out->config = pcm_config_afe_proxy_playback;
6333 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006334 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05306335 unsigned int channels = 0;
6336 /*Update config params to default if not set by the caller*/
6337 if (config->sample_rate == 0)
6338 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6339 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6340 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6341 if (config->format == AUDIO_FORMAT_DEFAULT)
6342 config->format = AUDIO_FORMAT_PCM_16_BIT;
6343
6344 channels = audio_channel_count_from_out_mask(out->channel_mask);
6345
Varun Balaraje49253e2017-07-06 19:48:56 +05306346 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6347 out->usecase = get_interactive_usecase(adev);
6348 out->config = pcm_config_low_latency;
6349 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306350 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006351 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6352 out->flags);
6353 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006354 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6355 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6356 out->config = pcm_config_mmap_playback;
6357 out->stream.start = out_start;
6358 out->stream.stop = out_stop;
6359 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6360 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306361 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6362 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006363 out->hal_output_suspend_supported =
6364 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6365 out->dynamic_pm_qos_config_supported =
6366 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6367 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006368 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6369 } else {
6370 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6371 //the mixer path will be a string similar to "low-latency-playback resume"
6372 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6373 strlcat(out->pm_qos_mixer_path,
6374 " resume", MAX_MIXER_PATH_LEN);
6375 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6376 out->pm_qos_mixer_path);
6377 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306378 out->config = pcm_config_low_latency;
6379 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6380 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6381 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306382 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6383 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6384 if (out->config.period_size <= 0) {
6385 ALOGE("Invalid configuration period size is not valid");
6386 ret = -EINVAL;
6387 goto error_open;
6388 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306389 } else {
6390 /* primary path is the default path selected if no other outputs are available/suitable */
6391 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6392 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6393 }
6394 out->hal_ip_format = format = out->format;
6395 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6396 out->hal_op_format = pcm_format_to_hal(out->config.format);
6397 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6398 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006399 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306400 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306401 if (out->hal_ip_format != out->hal_op_format) {
6402 uint32_t buffer_size = out->config.period_size *
6403 format_to_bitwidth_table[out->hal_op_format] *
6404 out->config.channels;
6405 out->convert_buffer = calloc(1, buffer_size);
6406 if (out->convert_buffer == NULL){
6407 ALOGE("Allocation failed for convert buffer for size %d",
6408 out->compr_config.fragment_size);
6409 ret = -ENOMEM;
6410 goto error_open;
6411 }
6412 ALOGD("Convert buffer allocated of size %d", buffer_size);
6413 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006414 }
6415
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006416 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6417 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306418
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006419 /* TODO remove this hardcoding and check why width is zero*/
6420 if (out->bit_width == 0)
6421 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306422 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006423 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006424 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306425 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306426 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006427 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6428 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6429 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006430 if(adev->primary_output == NULL)
6431 adev->primary_output = out;
6432 else {
6433 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006434 ret = -EEXIST;
6435 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006436 }
6437 }
6438
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006439 /* Check if this usecase is already existing */
6440 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006441 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6442 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006443 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006444 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006445 ret = -EEXIST;
6446 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006447 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006448
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006449 pthread_mutex_unlock(&adev->lock);
6450
6451 out->stream.common.get_sample_rate = out_get_sample_rate;
6452 out->stream.common.set_sample_rate = out_set_sample_rate;
6453 out->stream.common.get_buffer_size = out_get_buffer_size;
6454 out->stream.common.get_channels = out_get_channels;
6455 out->stream.common.get_format = out_get_format;
6456 out->stream.common.set_format = out_set_format;
6457 out->stream.common.standby = out_standby;
6458 out->stream.common.dump = out_dump;
6459 out->stream.common.set_parameters = out_set_parameters;
6460 out->stream.common.get_parameters = out_get_parameters;
6461 out->stream.common.add_audio_effect = out_add_audio_effect;
6462 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6463 out->stream.get_latency = out_get_latency;
6464 out->stream.set_volume = out_set_volume;
6465 out->stream.write = out_write;
6466 out->stream.get_render_position = out_get_render_position;
6467 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006468 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006469
Haynes Mathew George16081042017-05-31 17:16:49 -07006470 if (out->realtime)
6471 out->af_period_multiplier = af_period_multiplier;
6472 else
6473 out->af_period_multiplier = 1;
6474
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006475 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006476 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006477 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006478
6479 config->format = out->stream.common.get_format(&out->stream.common);
6480 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6481 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05306482 register_format(out->format, out->supported_formats);
6483 register_channel_mask(out->channel_mask, out->supported_channel_masks);
6484 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006485
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306486 /*
6487 By locking output stream before registering, we allow the callback
6488 to update stream's state only after stream's initial state is set to
6489 adev state.
6490 */
6491 lock_output_stream(out);
6492 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6493 pthread_mutex_lock(&adev->lock);
6494 out->card_status = adev->card_status;
6495 pthread_mutex_unlock(&adev->lock);
6496 pthread_mutex_unlock(&out->lock);
6497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006498 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306499 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006500 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006501
6502 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6503 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6504 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006505 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306506 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006507 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006508 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306509 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006510 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6511 out->usecase, PCM_PLAYBACK);
6512 hdlr_stream_cfg.flags = out->flags;
6513 hdlr_stream_cfg.type = PCM_PLAYBACK;
6514 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6515 &hdlr_stream_cfg);
6516 if (ret) {
6517 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6518 out->adsp_hdlr_stream_handle = NULL;
6519 }
6520 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306521 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006522 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006523 if (ret < 0) {
6524 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6525 out->ip_hdlr_handle = NULL;
6526 }
6527 }
Eric Laurent994a6932013-07-17 11:51:42 -07006528 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006529 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006530
6531error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306532 if (out->convert_buffer)
6533 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006534 free(out);
6535 *stream_out = NULL;
6536 ALOGD("%s: exit: ret %d", __func__, ret);
6537 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006538}
6539
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306540void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006541 struct audio_stream_out *stream)
6542{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006543 struct stream_out *out = (struct stream_out *)stream;
6544 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006545 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006546
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006547 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306548
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306549 // must deregister from sndmonitor first to prevent races
6550 // between the callback and close_stream
6551 audio_extn_snd_mon_unregister_listener(out);
6552
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006553 /* close adsp hdrl session before standby */
6554 if (out->adsp_hdlr_stream_handle) {
6555 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6556 if (ret)
6557 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6558 out->adsp_hdlr_stream_handle = NULL;
6559 }
6560
Manish Dewangan21a850a2017-08-14 12:03:55 +05306561 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006562 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6563 out->ip_hdlr_handle = NULL;
6564 }
6565
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006566 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306567 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006568 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306569 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306570 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006571 if(ret != 0)
6572 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6573 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006574 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006575 out_standby(&stream->common);
6576
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006577 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006578 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006579 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006580 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006581 if (out->compr_config.codec != NULL)
6582 free(out->compr_config.codec);
6583 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006584
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306585 out->a2dp_compress_mute = false;
6586
Varun Balaraje49253e2017-07-06 19:48:56 +05306587 if (is_interactive_usecase(out->usecase))
6588 free_interactive_usecase(adev, out->usecase);
6589
Ashish Jain83a6cc22016-06-28 14:34:17 +05306590 if (out->convert_buffer != NULL) {
6591 free(out->convert_buffer);
6592 out->convert_buffer = NULL;
6593 }
6594
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006595 if (adev->voice_tx_output == out)
6596 adev->voice_tx_output = NULL;
6597
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306598 if (adev->primary_output == out)
6599 adev->primary_output = NULL;
6600
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006601 pthread_cond_destroy(&out->cond);
6602 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006603 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006604 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006605}
6606
6607static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6608{
6609 struct audio_device *adev = (struct audio_device *)dev;
6610 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006611 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006612 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006613 int ret;
6614 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006615
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006616 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006617 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006618
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306619 if (!parms)
6620 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306621
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306622 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6623 if (ret >= 0) {
6624 /* When set to false, HAL should disable EC and NS */
6625 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6626 adev->bt_sco_on = true;
6627 else
6628 adev->bt_sco_on = false;
6629 }
6630
Naresh Tanniru4c630392014-05-12 01:05:52 +05306631 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006632 status = voice_set_parameters(adev, parms);
6633 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006634 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006635
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006636 status = platform_set_parameters(adev->platform, parms);
6637 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006638 goto done;
6639
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006640 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6641 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006642 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006643 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6644 adev->bluetooth_nrec = true;
6645 else
6646 adev->bluetooth_nrec = false;
6647 }
6648
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006649 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6650 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006651 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6652 adev->screen_off = false;
6653 else
6654 adev->screen_off = true;
6655 }
6656
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006657 ret = str_parms_get_int(parms, "rotation", &val);
6658 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006659 bool reverse_speakers = false;
6660 switch(val) {
6661 // FIXME: note that the code below assumes that the speakers are in the correct placement
6662 // relative to the user when the device is rotated 90deg from its default rotation. This
6663 // assumption is device-specific, not platform-specific like this code.
6664 case 270:
6665 reverse_speakers = true;
6666 break;
6667 case 0:
6668 case 90:
6669 case 180:
6670 break;
6671 default:
6672 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006673 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006674 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006675 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006676 // check and set swap
6677 // - check if orientation changed and speaker active
6678 // - set rotation and cache the rotation value
6679 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006680 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006681 }
6682
Mingming Yin514a8bc2014-07-29 15:22:21 -07006683 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6684 if (ret >= 0) {
6685 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6686 adev->bt_wb_speech_enabled = true;
6687 else
6688 adev->bt_wb_speech_enabled = false;
6689 }
6690
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006691 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6692 if (ret >= 0) {
6693 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306694 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08006695 if (audio_is_output_device(val) &&
6696 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006697 ALOGV("cache new ext disp type and edid");
6698 ret = platform_get_ext_disp_type(adev->platform);
6699 if (ret < 0) {
6700 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05306701 } else {
6702 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006703 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306704 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07006705 /*
6706 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6707 * Per AudioPolicyManager, USB device is higher priority than WFD.
6708 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6709 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6710 * starting voice call on USB
6711 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006712 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306713 if (ret >= 0)
6714 audio_extn_usb_add_device(device, atoi(value));
6715
Zhou Song6f862822017-11-06 17:27:57 +08006716 if (!audio_extn_usb_is_tunnel_supported()) {
6717 ALOGV("detected USB connect .. disable proxy");
6718 adev->allow_afe_proxy_usage = false;
6719 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006720 }
6721 }
6722
6723 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6724 if (ret >= 0) {
6725 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306726 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07006727 /*
6728 * The HDMI / Displayport disconnect handling has been moved to
6729 * audio extension to ensure that its parameters are not
6730 * invalidated prior to updating sysfs of the disconnect event
6731 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6732 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306733 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006734 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306735 if (ret >= 0)
6736 audio_extn_usb_remove_device(device, atoi(value));
6737
Zhou Song6f862822017-11-06 17:27:57 +08006738 if (!audio_extn_usb_is_tunnel_supported()) {
6739 ALOGV("detected USB disconnect .. enable proxy");
6740 adev->allow_afe_proxy_usage = true;
6741 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006742 }
6743 }
6744
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306745 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6746 if (ret >= 0) {
6747 struct audio_usecase *usecase;
6748 struct listnode *node;
6749 list_for_each(node, &adev->usecase_list) {
6750 usecase = node_to_item(node, struct audio_usecase, list);
6751 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07006752 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306753 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08006754
6755 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306756 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08006757 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306758 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306759 //force device switch to re configure encoder
6760 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306761 audio_extn_a2dp_set_handoff_mode(false);
6762 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306763 break;
6764 }
6765 }
6766 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006767
6768 //handle vr audio setparam
6769 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6770 value, sizeof(value));
6771 if (ret >= 0) {
6772 ALOGI("Setting vr mode to be %s", value);
6773 if (!strncmp(value, "true", 4)) {
6774 adev->vr_audio_mode_enabled = true;
6775 ALOGI("Setting vr mode to true");
6776 } else if (!strncmp(value, "false", 5)) {
6777 adev->vr_audio_mode_enabled = false;
6778 ALOGI("Setting vr mode to false");
6779 } else {
6780 ALOGI("wrong vr mode set");
6781 }
6782 }
6783
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306784 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006785done:
6786 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006787 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306788error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006789 ALOGV("%s: exit with code(%d)", __func__, status);
6790 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006791}
6792
6793static char* adev_get_parameters(const struct audio_hw_device *dev,
6794 const char *keys)
6795{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006796 struct audio_device *adev = (struct audio_device *)dev;
6797 struct str_parms *reply = str_parms_create();
6798 struct str_parms *query = str_parms_create_str(keys);
6799 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05306800 char value[256] = {0};
6801 int ret = 0;
6802
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006803 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006804 if (reply) {
6805 str_parms_destroy(reply);
6806 }
6807 if (query) {
6808 str_parms_destroy(query);
6809 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006810 ALOGE("adev_get_parameters: failed to create query or reply");
6811 return NULL;
6812 }
6813
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006814 //handle vr audio getparam
6815
6816 ret = str_parms_get_str(query,
6817 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6818 value, sizeof(value));
6819
6820 if (ret >= 0) {
6821 bool vr_audio_enabled = false;
6822 pthread_mutex_lock(&adev->lock);
6823 vr_audio_enabled = adev->vr_audio_mode_enabled;
6824 pthread_mutex_unlock(&adev->lock);
6825
6826 ALOGI("getting vr mode to %d", vr_audio_enabled);
6827
6828 if (vr_audio_enabled) {
6829 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6830 "true");
6831 goto exit;
6832 } else {
6833 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6834 "false");
6835 goto exit;
6836 }
6837 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006838
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006839 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006840 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08006841 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006842 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05306843 pthread_mutex_unlock(&adev->lock);
6844
Naresh Tannirud7205b62014-06-20 02:54:48 +05306845exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006846 str = str_parms_to_str(reply);
6847 str_parms_destroy(query);
6848 str_parms_destroy(reply);
6849
6850 ALOGV("%s: exit: returns - %s", __func__, str);
6851 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006852}
6853
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006854static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006855{
6856 return 0;
6857}
6858
6859static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
6860{
Haynes Mathew George5191a852013-09-11 14:19:36 -07006861 int ret;
6862 struct audio_device *adev = (struct audio_device *)dev;
6863 pthread_mutex_lock(&adev->lock);
6864 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07006865 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07006866 pthread_mutex_unlock(&adev->lock);
6867 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006868}
6869
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006870static int adev_set_master_volume(struct audio_hw_device *dev __unused,
6871 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006872{
6873 return -ENOSYS;
6874}
6875
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006876static int adev_get_master_volume(struct audio_hw_device *dev __unused,
6877 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006878{
6879 return -ENOSYS;
6880}
6881
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006882static int adev_set_master_mute(struct audio_hw_device *dev __unused,
6883 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006884{
6885 return -ENOSYS;
6886}
6887
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006888static int adev_get_master_mute(struct audio_hw_device *dev __unused,
6889 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006890{
6891 return -ENOSYS;
6892}
6893
6894static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
6895{
6896 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07006897 struct listnode *node;
6898 struct audio_usecase *usecase = NULL;
6899 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006900 pthread_mutex_lock(&adev->lock);
6901 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006902 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006903 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08006904 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07006905 list_for_each(node, &adev->usecase_list) {
6906 usecase = node_to_item(node, struct audio_usecase, list);
6907 if (usecase->type == VOICE_CALL)
6908 break;
6909 }
6910 if (usecase &&
6911 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
6912 ret = audio_extn_usb_check_and_set_svc_int(usecase,
6913 true);
6914 if (ret != 0) {
6915 /* default service interval was successfully updated,
6916 reopen USB backend with new service interval */
6917 check_usecases_codec_backend(adev,
6918 usecase,
6919 usecase->out_snd_device);
6920 }
6921 }
6922
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006923 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07006924 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006925 adev->current_call_output = NULL;
6926 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006927 }
6928 pthread_mutex_unlock(&adev->lock);
6929 return 0;
6930}
6931
6932static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
6933{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006934 int ret;
6935
6936 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08006937 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006938 ret = voice_set_mic_mute((struct audio_device *)dev, state);
6939 pthread_mutex_unlock(&adev->lock);
6940
6941 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006942}
6943
6944static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
6945{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006946 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006947 return 0;
6948}
6949
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006950static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006951 const struct audio_config *config)
6952{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006953 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006954
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006955 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
6956 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006957}
6958
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006959static bool adev_input_allow_hifi_record(struct audio_device *adev,
6960 audio_devices_t devices,
6961 audio_input_flags_t flags,
6962 audio_source_t source) {
6963 const bool allowed = true;
6964
6965 if (!audio_is_usb_in_device(devices))
6966 return !allowed;
6967
6968 switch (flags) {
6969 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006970 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07006971 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
6972 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006973 default:
6974 return !allowed;
6975 }
6976
6977 switch (source) {
6978 case AUDIO_SOURCE_DEFAULT:
6979 case AUDIO_SOURCE_MIC:
6980 case AUDIO_SOURCE_UNPROCESSED:
6981 break;
6982 default:
6983 return !allowed;
6984 }
6985
6986 switch (adev->mode) {
6987 case 0:
6988 break;
6989 default:
6990 return !allowed;
6991 }
6992
6993 return allowed;
6994}
6995
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006996static int adev_update_voice_comm_input_stream(struct stream_in *in,
6997 struct audio_config *config)
6998{
6999 bool valid_rate = (config->sample_rate == 8000 ||
7000 config->sample_rate == 16000 ||
7001 config->sample_rate == 32000 ||
7002 config->sample_rate == 48000);
7003 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
7004
7005#ifndef COMPRESS_VOIP_ENABLED
kunleizd96526c2018-04-09 11:12:32 +08007006 if (valid_rate && valid_ch &&
7007 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007008 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7009 in->config = default_pcm_config_voip_copp;
7010 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
7011 DEFAULT_VOIP_BUF_DURATION_MS,
7012 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
7013 } else {
kunleizbdd9ad02018-04-24 10:53:17 +08007014 ALOGW("%s No valid input in voip, use defaults"
7015 "sample rate %u, channel mask 0x%X",
7016 __func__, config->sample_rate, in->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007017 }
7018 in->config.rate = config->sample_rate;
7019 in->sample_rate = config->sample_rate;
7020#else
7021 //XXX needed for voice_extn_compress_voip_open_input_stream
7022 in->config.rate = config->sample_rate;
7023 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7024 voice_extn_compress_voip_is_active(in->dev)) &&
7025 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7026 valid_rate && valid_ch) {
7027 voice_extn_compress_voip_open_input_stream(in);
7028 // update rate entries to match config from AF
7029 in->config.rate = config->sample_rate;
7030 in->sample_rate = config->sample_rate;
7031 } else {
7032 ALOGW("%s compress voip not active, use defaults", __func__);
7033 }
7034#endif
7035 return 0;
7036}
7037
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007038static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007039 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007040 audio_devices_t devices,
7041 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007042 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307043 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007044 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007045 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007046{
7047 struct audio_device *adev = (struct audio_device *)dev;
7048 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007049 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007050 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007051 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05307052 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007053 bool is_usb_dev = audio_is_usb_in_device(devices);
7054 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
7055 devices,
7056 flags,
7057 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307058
kunleizdff872d2018-08-20 14:40:33 +08007059 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007060 is_usb_dev = false;
7061 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
7062 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
7063 __func__, devices);
7064 }
7065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007066 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007067
7068 if (!(is_usb_dev && may_use_hifi_record)) {
7069 if (config->sample_rate == 0)
7070 config->sample_rate = 48000;
7071 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7072 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7073 if (config->format == AUDIO_FORMAT_DEFAULT)
7074 config->format = AUDIO_FORMAT_PCM_16_BIT;
7075
7076 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
7077
7078 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
7079 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05307080 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007081
7082 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007083
7084 if (!in) {
7085 ALOGE("failed to allocate input stream");
7086 return -ENOMEM;
7087 }
7088
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307089 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307090 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7091 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007092 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007093 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007095 in->stream.common.get_sample_rate = in_get_sample_rate;
7096 in->stream.common.set_sample_rate = in_set_sample_rate;
7097 in->stream.common.get_buffer_size = in_get_buffer_size;
7098 in->stream.common.get_channels = in_get_channels;
7099 in->stream.common.get_format = in_get_format;
7100 in->stream.common.set_format = in_set_format;
7101 in->stream.common.standby = in_standby;
7102 in->stream.common.dump = in_dump;
7103 in->stream.common.set_parameters = in_set_parameters;
7104 in->stream.common.get_parameters = in_get_parameters;
7105 in->stream.common.add_audio_effect = in_add_audio_effect;
7106 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7107 in->stream.set_gain = in_set_gain;
7108 in->stream.read = in_read;
7109 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307110 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007111
7112 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007113 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007114 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007115 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007116 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007117 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007118 in->bit_width = 16;
7119 in->af_period_multiplier = 1;
7120
7121 /* Update config params with the requested sample rate and channels */
7122 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
7123 (adev->mode != AUDIO_MODE_IN_CALL)) {
7124 ret = -EINVAL;
7125 goto err_open;
7126 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007127
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007128 if (is_usb_dev && may_use_hifi_record) {
7129 /* HiFi record selects an appropriate format, channel, rate combo
7130 depending on sink capabilities*/
7131 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7132 &config->format,
7133 &in->supported_formats[0],
7134 MAX_SUPPORTED_FORMATS,
7135 &config->channel_mask,
7136 &in->supported_channel_masks[0],
7137 MAX_SUPPORTED_CHANNEL_MASKS,
7138 &config->sample_rate,
7139 &in->supported_sample_rates[0],
7140 MAX_SUPPORTED_SAMPLE_RATES);
7141 if (ret != 0) {
7142 ret = -EINVAL;
7143 goto err_open;
7144 }
7145 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007146 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307147 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05307148 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
7149 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
7150 in->config.format = PCM_FORMAT_S32_LE;
7151 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307152 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
7153 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
7154 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
7155 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7156 bool ret_error = false;
7157 in->bit_width = 24;
7158 /* 24 bit is restricted to UNPROCESSED source only,also format supported
7159 from HAL is 24_packed and 8_24
7160 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
7161 24_packed return error indicating supported format is 24_packed
7162 *> In case of any other source requesting 24 bit or float return error
7163 indicating format supported is 16 bit only.
7164
7165 on error flinger will retry with supported format passed
7166 */
7167 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
7168 (source != AUDIO_SOURCE_CAMCORDER)) {
7169 config->format = AUDIO_FORMAT_PCM_16_BIT;
7170 if (config->sample_rate > 48000)
7171 config->sample_rate = 48000;
7172 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07007173 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
7174 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307175 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
7176 ret_error = true;
7177 }
7178
7179 if (ret_error) {
7180 ret = -EINVAL;
7181 goto err_open;
7182 }
7183 }
7184
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007185 in->channel_mask = config->channel_mask;
7186 in->format = config->format;
7187
7188 in->usecase = USECASE_AUDIO_RECORD;
7189 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
7190 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
7191 is_low_latency = true;
7192#if LOW_LATENCY_CAPTURE_USE_CASE
7193 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
7194#endif
7195 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
7196 }
7197
7198 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
7199 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
7200 in->realtime = 0;
7201 in->usecase = USECASE_AUDIO_RECORD_MMAP;
7202 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07007203 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007204 in->stream.start = in_start;
7205 in->stream.stop = in_stop;
7206 in->stream.create_mmap_buffer = in_create_mmap_buffer;
7207 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007208 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007209 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
7210 } else if (in->realtime) {
7211 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07007212 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007213 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007214 in->sample_rate = in->config.rate;
7215 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07007216 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007217 in->usecase = USECASE_AUDIO_RECORD_HIFI;
7218 in->config = pcm_config_audio_capture;
7219 frame_size = audio_stream_in_frame_size(&in->stream);
7220 buffer_size = get_input_buffer_size(config->sample_rate,
7221 config->format,
7222 channel_count,
7223 false /*is_low_latency*/);
7224 in->config.period_size = buffer_size / frame_size;
7225 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007226 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07007227 switch (config->format) {
7228 case AUDIO_FORMAT_PCM_32_BIT:
7229 in->bit_width = 32;
7230 break;
7231 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
7232 case AUDIO_FORMAT_PCM_8_24_BIT:
7233 in->bit_width = 24;
7234 break;
7235 default:
7236 in->bit_width = 16;
7237 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007238 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007239 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007240 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05307241 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007242 if (config->sample_rate == 0)
7243 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7244 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
7245 config->sample_rate != 8000) {
7246 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7247 ret = -EINVAL;
7248 goto err_open;
7249 }
7250 if (config->format == AUDIO_FORMAT_DEFAULT)
7251 config->format = AUDIO_FORMAT_PCM_16_BIT;
7252 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
7253 config->format = AUDIO_FORMAT_PCM_16_BIT;
7254 ret = -EINVAL;
7255 goto err_open;
7256 }
7257
7258 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
7259 in->config = pcm_config_afe_proxy_record;
7260 in->config.channels = channel_count;
7261 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307262 in->sample_rate = config->sample_rate;
Haynes Mathew George46740472017-10-27 18:40:12 -07007263 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05307264 int ret_val;
7265 pthread_mutex_lock(&adev->lock);
7266 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
7267 in, config, &channel_mask_updated);
7268 pthread_mutex_unlock(&adev->lock);
7269
7270 if (!ret_val) {
7271 if (channel_mask_updated == true) {
7272 ALOGD("%s: return error to retry with updated channel mask (%#x)",
7273 __func__, config->channel_mask);
7274 ret = -EINVAL;
7275 goto err_open;
7276 }
7277 ALOGD("%s: created multi-channel session succesfully",__func__);
7278 } else if (audio_extn_compr_cap_enabled() &&
7279 audio_extn_compr_cap_format_supported(config->format) &&
7280 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
7281 audio_extn_compr_cap_init(in);
7282 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05307283 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05307284 ret = audio_extn_cin_configure_input_stream(in);
7285 if (ret)
7286 goto err_open;
7287 } else {
7288 in->config = pcm_config_audio_capture;
7289 in->config.rate = config->sample_rate;
7290 in->config.format = pcm_format_from_audio_format(config->format);
7291 in->config.channels = channel_count;
7292 in->sample_rate = config->sample_rate;
7293 in->format = config->format;
7294 frame_size = audio_stream_in_frame_size(&in->stream);
7295 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07007296 config->format,
7297 channel_count,
7298 is_low_latency);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307299 in->config.period_size = buffer_size / frame_size;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007300
Revathi Uddarajud2634032017-12-07 14:42:34 +05307301 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
7302 /* optionally use VOIP usecase depending on config(s) */
7303 ret = adev_update_voice_comm_input_stream(in, config);
7304 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007305
Revathi Uddarajud2634032017-12-07 14:42:34 +05307306 if (ret) {
7307 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
7308 goto err_open;
7309 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007310 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007311 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307312 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7313 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007314 devices, flags, in->format,
7315 in->sample_rate, in->bit_width,
7316 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307317 register_format(in->format, in->supported_formats);
7318 register_channel_mask(in->channel_mask, in->supported_channel_masks);
7319 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307320
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007321 /* This stream could be for sound trigger lab,
7322 get sound trigger pcm if present */
7323 audio_extn_sound_trigger_check_and_get_session(in);
7324
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307325 lock_input_stream(in);
7326 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
7327 pthread_mutex_lock(&adev->lock);
7328 in->card_status = adev->card_status;
7329 pthread_mutex_unlock(&adev->lock);
7330 pthread_mutex_unlock(&in->lock);
7331
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007332 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07007333 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007334 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007335
7336err_open:
7337 free(in);
7338 *stream_in = NULL;
7339 return ret;
7340}
7341
7342static void adev_close_input_stream(struct audio_hw_device *dev,
7343 struct audio_stream_in *stream)
7344{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007345 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007346 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007347 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307348
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307349 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007350
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307351 // must deregister from sndmonitor first to prevent races
7352 // between the callback and close_stream
7353 audio_extn_snd_mon_unregister_listener(stream);
7354
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307355 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07007356 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307357
Pallavid7c7a272018-01-16 11:22:55 +05307358 if (in == NULL) {
7359 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
7360 return;
7361 }
7362
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007363 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307364 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007365 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307366 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007367 if (ret != 0)
7368 ALOGE("%s: Compress voip input cannot be closed, error:%d",
7369 __func__, ret);
7370 } else
7371 in_standby(&stream->common);
7372
Revathi Uddarajud2634032017-12-07 14:42:34 +05307373 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07007374 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007375 audio_extn_ssr_deinit();
7376 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007377
Garmond Leunge2433c32017-09-28 21:51:22 -07007378 if (audio_extn_ffv_get_stream() == in) {
7379 audio_extn_ffv_stream_deinit();
7380 }
7381
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307382 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07007383 audio_extn_compr_cap_format_supported(in->config.format))
7384 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05307385
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307386 if (audio_extn_cin_attached_usecase(in->usecase))
7387 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007388
Mingming Yinfd7607b2016-01-22 12:48:44 -08007389 if (in->is_st_session) {
7390 ALOGV("%s: sound trigger pcm stop lab", __func__);
7391 audio_extn_sound_trigger_stop_lab(in);
7392 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007393 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307394 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007395 return;
7396}
7397
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307398int adev_create_audio_patch(struct audio_hw_device *dev,
7399 unsigned int num_sources,
7400 const struct audio_port_config *sources,
7401 unsigned int num_sinks,
7402 const struct audio_port_config *sinks,
7403 audio_patch_handle_t *handle)
7404{
7405
7406
7407 return audio_extn_hw_loopback_create_audio_patch(dev,
7408 num_sources,
7409 sources,
7410 num_sinks,
7411 sinks,
7412 handle);
7413
7414}
7415
7416int adev_release_audio_patch(struct audio_hw_device *dev,
7417 audio_patch_handle_t handle)
7418{
7419 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
7420}
7421
7422int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
7423{
7424 return audio_extn_hw_loopback_get_audio_port(dev, config);
7425}
7426
7427int adev_set_audio_port_config(struct audio_hw_device *dev,
7428 const struct audio_port_config *config)
7429{
7430 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
7431}
7432
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007433static int adev_dump(const audio_hw_device_t *device __unused,
7434 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007435{
7436 return 0;
7437}
7438
7439static int adev_close(hw_device_t *device)
7440{
7441 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07007442
7443 if (!adev)
7444 return 0;
7445
7446 pthread_mutex_lock(&adev_init_lock);
7447
7448 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307449 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007450 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08007451 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307452 audio_extn_utils_release_streams_cfg_lists(
7453 &adev->streams_output_cfg_list,
7454 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307455 if (audio_extn_qaf_is_enabled())
7456 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007457 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007458 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007459 free(adev->snd_dev_ref_cnt);
7460 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007461 if (adev->adm_deinit)
7462 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307463 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007464 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307465 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307466 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007467 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307468 if (adev->device_cfg_params) {
7469 free(adev->device_cfg_params);
7470 adev->device_cfg_params = NULL;
7471 }
Kiran Kandi910e1862013-10-29 13:29:42 -07007472 free(device);
7473 adev = NULL;
7474 }
7475 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007477 return 0;
7478}
7479
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007480/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
7481 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
7482 * just that it _might_ work.
7483 */
7484static int period_size_is_plausible_for_low_latency(int period_size)
7485{
7486 switch (period_size) {
7487 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07007488 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007489 case 240:
7490 case 320:
7491 case 480:
7492 return 1;
7493 default:
7494 return 0;
7495 }
7496}
7497
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307498static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
7499{
7500 bool is_snd_card_status = false;
7501 bool is_ext_device_status = false;
7502 char value[32];
7503 int card = -1;
7504 card_status_t status;
7505
7506 if (cookie != adev || !parms)
7507 return;
7508
7509 if (!parse_snd_card_status(parms, &card, &status)) {
7510 is_snd_card_status = true;
7511 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
7512 is_ext_device_status = true;
7513 } else {
7514 // not a valid event
7515 return;
7516 }
7517
7518 pthread_mutex_lock(&adev->lock);
7519 if (card == adev->snd_card || is_ext_device_status) {
7520 if (is_snd_card_status && adev->card_status != status) {
7521 adev->card_status = status;
7522 platform_snd_card_update(adev->platform, status);
7523 audio_extn_fm_set_parameters(adev, parms);
7524 } else if (is_ext_device_status) {
7525 platform_set_parameters(adev->platform, parms);
7526 }
7527 }
7528 pthread_mutex_unlock(&adev->lock);
7529 return;
7530}
7531
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307532/* out and adev lock held */
7533static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
7534{
7535 struct audio_usecase *uc_info;
7536 float left_p;
7537 float right_p;
7538 audio_devices_t devices;
7539
7540 uc_info = get_usecase_from_list(adev, out->usecase);
7541 if (uc_info == NULL) {
7542 ALOGE("%s: Could not find the usecase (%d) in the list",
7543 __func__, out->usecase);
7544 return -EINVAL;
7545 }
7546
7547 ALOGD("%s: enter: usecase(%d: %s)", __func__,
7548 out->usecase, use_case_table[out->usecase]);
7549
7550 if (restore) {
7551 // restore A2DP device for active usecases and unmute if required
7552 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
7553 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
7554 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
7555 select_devices(adev, uc_info->id);
7556 pthread_mutex_lock(&out->compr_mute_lock);
7557 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7558 (out->a2dp_compress_mute)) {
7559 out->a2dp_compress_mute = false;
7560 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
7561 }
7562 pthread_mutex_unlock(&out->compr_mute_lock);
7563 }
7564 } else {
7565 // mute compress stream if suspended
7566 pthread_mutex_lock(&out->compr_mute_lock);
7567 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7568 (!out->a2dp_compress_mute)) {
7569 if (!out->standby) {
7570 ALOGD("%s: selecting speaker and muting stream", __func__);
7571 devices = out->devices;
7572 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
7573 left_p = out->volume_l;
7574 right_p = out->volume_r;
7575 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7576 compress_pause(out->compr);
7577 out_set_compr_volume(&out->stream, (float)0, (float)0);
7578 out->a2dp_compress_mute = true;
7579 select_devices(adev, out->usecase);
7580 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7581 compress_resume(out->compr);
7582 out->devices = devices;
7583 out->volume_l = left_p;
7584 out->volume_r = right_p;
7585 }
7586 }
7587 pthread_mutex_unlock(&out->compr_mute_lock);
7588 }
7589 ALOGV("%s: exit", __func__);
7590 return 0;
7591}
7592
7593int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
7594{
7595 int ret = 0;
7596
7597 lock_output_stream(out);
7598 pthread_mutex_lock(&adev->lock);
7599
7600 ret = check_a2dp_restore_l(adev, out, restore);
7601
7602 pthread_mutex_unlock(&adev->lock);
7603 pthread_mutex_unlock(&out->lock);
7604 return ret;
7605}
7606
Haynes Mathew George01156f92018-04-13 15:29:54 -07007607void adev_on_battery_status_changed(bool charging)
7608{
7609 pthread_mutex_lock(&adev->lock);
7610 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
7611 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08007612 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07007613 pthread_mutex_unlock(&adev->lock);
7614}
7615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007616static int adev_open(const hw_module_t *module, const char *name,
7617 hw_device_t **device)
7618{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307619 int ret;
7620
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007621 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007622 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
7623
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007624 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07007625 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007626 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07007627 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007628 ALOGD("%s: returning existing instance of adev", __func__);
7629 ALOGD("%s: exit", __func__);
7630 pthread_mutex_unlock(&adev_init_lock);
7631 return 0;
7632 }
7633
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007634 adev = calloc(1, sizeof(struct audio_device));
7635
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007636 if (!adev) {
7637 pthread_mutex_unlock(&adev_init_lock);
7638 return -ENOMEM;
7639 }
7640
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007641 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
7642
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05307643#ifdef DYNAMIC_LOG_ENABLED
7644 register_for_dynamic_logging("hal");
7645#endif
7646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007647 adev->device.common.tag = HARDWARE_DEVICE_TAG;
7648 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7649 adev->device.common.module = (struct hw_module_t *)module;
7650 adev->device.common.close = adev_close;
7651
7652 adev->device.init_check = adev_init_check;
7653 adev->device.set_voice_volume = adev_set_voice_volume;
7654 adev->device.set_master_volume = adev_set_master_volume;
7655 adev->device.get_master_volume = adev_get_master_volume;
7656 adev->device.set_master_mute = adev_set_master_mute;
7657 adev->device.get_master_mute = adev_get_master_mute;
7658 adev->device.set_mode = adev_set_mode;
7659 adev->device.set_mic_mute = adev_set_mic_mute;
7660 adev->device.get_mic_mute = adev_get_mic_mute;
7661 adev->device.set_parameters = adev_set_parameters;
7662 adev->device.get_parameters = adev_get_parameters;
7663 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
7664 adev->device.open_output_stream = adev_open_output_stream;
7665 adev->device.close_output_stream = adev_close_output_stream;
7666 adev->device.open_input_stream = adev_open_input_stream;
7667 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307668 adev->device.create_audio_patch = adev_create_audio_patch;
7669 adev->device.release_audio_patch = adev_release_audio_patch;
7670 adev->device.get_audio_port = adev_get_audio_port;
7671 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007672 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307673 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007674
7675 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007676 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08007677 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007678 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007679 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007680 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08007681 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07007682 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307683 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07007684 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07007685 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007686 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08007687 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08007688 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007689 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05307690 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307691 adev->perf_lock_opts[0] = 0x101;
7692 adev->perf_lock_opts[1] = 0x20E;
7693 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007694 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307695
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007696 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07007697 adev->platform = platform_init(adev);
7698 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007699 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007700 free(adev->snd_dev_ref_cnt);
7701 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007702 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07007703 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7704 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08007705 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007706 return -EINVAL;
7707 }
Eric Laurentc4aef752013-09-12 17:45:53 -07007708
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307709 if (audio_extn_qaf_is_enabled()) {
7710 ret = audio_extn_qaf_init(adev);
7711 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007712 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307713 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007714 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307715 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7716 *device = NULL;
7717 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307718 return ret;
7719 }
7720
7721 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
7722 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
7723 }
7724
Eric Laurentc4aef752013-09-12 17:45:53 -07007725 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
7726 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
7727 if (adev->visualizer_lib == NULL) {
7728 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
7729 } else {
7730 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
7731 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007732 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007733 "visualizer_hal_start_output");
7734 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007735 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007736 "visualizer_hal_stop_output");
7737 }
7738 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05307739 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08007740 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007741 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307742 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007743 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07007744
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007745 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
7746 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
7747 if (adev->offload_effects_lib == NULL) {
7748 ALOGE("%s: DLOPEN failed for %s", __func__,
7749 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7750 } else {
7751 ALOGV("%s: DLOPEN successful for %s", __func__,
7752 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7753 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05307754 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007755 "offload_effects_bundle_hal_start_output");
7756 adev->offload_effects_stop_output =
7757 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
7758 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007759 adev->offload_effects_set_hpx_state =
7760 (int (*)(bool))dlsym(adev->offload_effects_lib,
7761 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05307762 adev->offload_effects_get_parameters =
7763 (void (*)(struct str_parms *, struct str_parms *))
7764 dlsym(adev->offload_effects_lib,
7765 "offload_effects_bundle_get_parameters");
7766 adev->offload_effects_set_parameters =
7767 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
7768 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007769 }
7770 }
7771
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007772 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
7773 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
7774 if (adev->adm_lib == NULL) {
7775 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
7776 } else {
7777 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
7778 adev->adm_init = (adm_init_t)
7779 dlsym(adev->adm_lib, "adm_init");
7780 adev->adm_deinit = (adm_deinit_t)
7781 dlsym(adev->adm_lib, "adm_deinit");
7782 adev->adm_register_input_stream = (adm_register_input_stream_t)
7783 dlsym(adev->adm_lib, "adm_register_input_stream");
7784 adev->adm_register_output_stream = (adm_register_output_stream_t)
7785 dlsym(adev->adm_lib, "adm_register_output_stream");
7786 adev->adm_deregister_stream = (adm_deregister_stream_t)
7787 dlsym(adev->adm_lib, "adm_deregister_stream");
7788 adev->adm_request_focus = (adm_request_focus_t)
7789 dlsym(adev->adm_lib, "adm_request_focus");
7790 adev->adm_abandon_focus = (adm_abandon_focus_t)
7791 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007792 adev->adm_set_config = (adm_set_config_t)
7793 dlsym(adev->adm_lib, "adm_set_config");
7794 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
7795 dlsym(adev->adm_lib, "adm_request_focus_v2");
7796 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
7797 dlsym(adev->adm_lib, "adm_is_noirq_avail");
7798 adev->adm_on_routing_change = (adm_on_routing_change_t)
7799 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007800 }
7801 }
7802
Mingming Yin514a8bc2014-07-29 15:22:21 -07007803 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007804 //initialize this to false for now,
7805 //this will be set to true through set param
7806 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07007807
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07007808 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007809 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007810 adev->dsp_bit_width_enforce_mode =
7811 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007812
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307813 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
7814 &adev->streams_output_cfg_list,
7815 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007816
Kiran Kandi910e1862013-10-29 13:29:42 -07007817 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007818
7819 char value[PROPERTY_VALUE_MAX];
7820 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007821 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007822 trial = atoi(value);
7823 if (period_size_is_plausible_for_low_latency(trial)) {
7824 pcm_config_low_latency.period_size = trial;
7825 pcm_config_low_latency.start_threshold = trial / 4;
7826 pcm_config_low_latency.avail_min = trial / 4;
7827 configured_low_latency_capture_period_size = trial;
7828 }
7829 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007830 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007831 trial = atoi(value);
7832 if (period_size_is_plausible_for_low_latency(trial)) {
7833 configured_low_latency_capture_period_size = trial;
7834 }
7835 }
7836
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08007837 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
7838
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007839 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007840 af_period_multiplier = atoi(value);
7841 if (af_period_multiplier < 0)
7842 af_period_multiplier = 2;
7843 else if (af_period_multiplier > 4)
7844 af_period_multiplier = 4;
7845
7846 ALOGV("new period_multiplier = %d", af_period_multiplier);
7847 }
7848
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007849 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007850 pthread_mutex_unlock(&adev_init_lock);
7851
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007852 if (adev->adm_init)
7853 adev->adm_data = adev->adm_init();
7854
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307855 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307856 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007857 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307858
7859 audio_extn_snd_mon_init();
7860 pthread_mutex_lock(&adev->lock);
7861 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
7862 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07007863 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
7864 /*
7865 * if the battery state callback happens before charging can be queried,
7866 * it will be guarded with the adev->lock held in the cb function and so
7867 * the callback value will reflect the latest state
7868 */
7869 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307870 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08007871 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
7872 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307873 /* Allocate memory for Device config params */
7874 adev->device_cfg_params = (struct audio_device_config_param*)
7875 calloc(platform_get_max_codec_backend(),
7876 sizeof(struct audio_device_config_param));
7877 if (adev->device_cfg_params == NULL)
7878 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307879
Eric Laurent994a6932013-07-17 11:51:42 -07007880 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007881 return 0;
7882}
7883
7884static struct hw_module_methods_t hal_module_methods = {
7885 .open = adev_open,
7886};
7887
7888struct audio_module HAL_MODULE_INFO_SYM = {
7889 .common = {
7890 .tag = HARDWARE_MODULE_TAG,
7891 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
7892 .hal_api_version = HARDWARE_HAL_API_VERSION,
7893 .id = AUDIO_HARDWARE_MODULE_ID,
7894 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08007895 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007896 .methods = &hal_module_methods,
7897 },
7898};