blob: f8c5563243d9e12bd6944026399c21a1dde5aefc [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aalique Grahame22e49102018-12-18 14:23:57 -08002 * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070066#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070068#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053077#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080080#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080081
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053082#ifdef DYNAMIC_LOG_ENABLED
83#include <log_xml_parser.h>
84#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
85#include <log_utils.h>
86#endif
87
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053089/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
90#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070092#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053093#define PCM_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
Aalique Grahame22e49102018-12-18 14:23:57 -080096#define RECORD_GAIN_MIN 0.0f
97#define RECORD_GAIN_MAX 1.0f
98#define RECORD_VOLUME_CTL_MAX 0x2000
99
100/* treat as unsigned Q1.13 */
101#define APP_TYPE_GAIN_DEFAULT 0x2000
102
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700103#define PROXY_OPEN_RETRY_COUNT 100
104#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800105
Aalique Grahame22e49102018-12-18 14:23:57 -0800106#ifndef USE_DEEP_AS_PRIMARY_OUTPUT
Mingming Yin08c7e312015-03-16 18:10:58 -0700107#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
108#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
109#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800110#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700111#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
112#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800113
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700114#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700115#define DEFAULT_VOIP_BUF_DURATION_MS 20
116#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
117#define DEFAULT_VOIP_SAMP_RATE 48000
118
119#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
120
121struct pcm_config default_pcm_config_voip_copp = {
122 .channels = 1,
123 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
124 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
125 .period_count = 2,
126 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800127 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
128 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700129};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700130
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700131#define MIN_CHANNEL_COUNT 1
132#define DEFAULT_CHANNEL_COUNT 2
133#define MAX_HIFI_CHANNEL_COUNT 8
134
Aalique Grahame22e49102018-12-18 14:23:57 -0800135#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
136#define MAX_CHANNEL_COUNT 1
137#else
138#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
139#define XSTR(x) STR(x)
140#define STR(x) #x
141#endif
142
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700143static unsigned int configured_low_latency_capture_period_size =
144 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
145
Haynes Mathew George16081042017-05-31 17:16:49 -0700146#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
147#define MMAP_PERIOD_COUNT_MIN 32
148#define MMAP_PERIOD_COUNT_MAX 512
149#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
150
Aalique Grahame22e49102018-12-18 14:23:57 -0800151/* This constant enables extended precision handling.
152 * TODO The flag is off until more testing is done.
153 */
154static const bool k_enable_extended_precision = false;
155
Eric Laurentb23d5282013-05-14 15:27:20 -0700156struct pcm_config pcm_config_deep_buffer = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
160 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
163 .stop_threshold = INT_MAX,
164 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
165};
166
167struct pcm_config pcm_config_low_latency = {
168 .channels = 2,
169 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
170 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
171 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
172 .format = PCM_FORMAT_S16_LE,
173 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
174 .stop_threshold = INT_MAX,
175 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
176};
177
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700178static int af_period_multiplier = 4;
179struct pcm_config pcm_config_rt = {
180 .channels = 2,
181 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
182 .period_size = ULL_PERIOD_SIZE, //1 ms
183 .period_count = 512, //=> buffer size is 512ms
184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
186 .stop_threshold = INT_MAX,
187 .silence_threshold = 0,
188 .silence_size = 0,
189 .avail_min = ULL_PERIOD_SIZE, //1 ms
190};
191
Eric Laurentb23d5282013-05-14 15:27:20 -0700192struct pcm_config pcm_config_hdmi_multi = {
193 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
194 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
195 .period_size = HDMI_MULTI_PERIOD_SIZE,
196 .period_count = HDMI_MULTI_PERIOD_COUNT,
197 .format = PCM_FORMAT_S16_LE,
198 .start_threshold = 0,
199 .stop_threshold = INT_MAX,
200 .avail_min = 0,
201};
202
Haynes Mathew George16081042017-05-31 17:16:49 -0700203struct pcm_config pcm_config_mmap_playback = {
204 .channels = 2,
205 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
206 .period_size = MMAP_PERIOD_SIZE,
207 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
208 .format = PCM_FORMAT_S16_LE,
209 .start_threshold = MMAP_PERIOD_SIZE*8,
210 .stop_threshold = INT32_MAX,
211 .silence_threshold = 0,
212 .silence_size = 0,
213 .avail_min = MMAP_PERIOD_SIZE, //1 ms
214};
215
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700216struct pcm_config pcm_config_hifi = {
217 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
218 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
219 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
220 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
221 .format = PCM_FORMAT_S24_3LE,
222 .start_threshold = 0,
223 .stop_threshold = INT_MAX,
224 .avail_min = 0,
225};
226
Eric Laurentb23d5282013-05-14 15:27:20 -0700227struct pcm_config pcm_config_audio_capture = {
228 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700229 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
230 .format = PCM_FORMAT_S16_LE,
231};
232
Haynes Mathew George16081042017-05-31 17:16:49 -0700233struct pcm_config pcm_config_mmap_capture = {
234 .channels = 2,
235 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
236 .period_size = MMAP_PERIOD_SIZE,
237 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
238 .format = PCM_FORMAT_S16_LE,
239 .start_threshold = 0,
240 .stop_threshold = INT_MAX,
241 .silence_threshold = 0,
242 .silence_size = 0,
243 .avail_min = MMAP_PERIOD_SIZE, //1 ms
244};
245
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700246#define AFE_PROXY_CHANNEL_COUNT 2
247#define AFE_PROXY_SAMPLING_RATE 48000
248
249#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
250#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
251
252struct pcm_config pcm_config_afe_proxy_playback = {
253 .channels = AFE_PROXY_CHANNEL_COUNT,
254 .rate = AFE_PROXY_SAMPLING_RATE,
255 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
256 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
257 .format = PCM_FORMAT_S16_LE,
258 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
259 .stop_threshold = INT_MAX,
260 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
261};
262
263#define AFE_PROXY_RECORD_PERIOD_SIZE 768
264#define AFE_PROXY_RECORD_PERIOD_COUNT 4
265
Aalique Grahame22e49102018-12-18 14:23:57 -0800266struct pcm_config pcm_config_audio_capture_rt = {
267 .channels = 2,
268 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
269 .period_size = ULL_PERIOD_SIZE,
270 .period_count = 512,
271 .format = PCM_FORMAT_S16_LE,
272 .start_threshold = 0,
273 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
274 .silence_threshold = 0,
275 .silence_size = 0,
276 .avail_min = ULL_PERIOD_SIZE, //1 ms
277};
278
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700279struct pcm_config pcm_config_afe_proxy_record = {
280 .channels = AFE_PROXY_CHANNEL_COUNT,
281 .rate = AFE_PROXY_SAMPLING_RATE,
282 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
283 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
284 .format = PCM_FORMAT_S16_LE,
285 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
286 .stop_threshold = INT_MAX,
287 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
288};
289
Ashish Jainf1eaa582016-05-23 20:54:24 +0530290#define AUDIO_MAX_PCM_FORMATS 7
291
292const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
293 [AUDIO_FORMAT_DEFAULT] = 0,
294 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
295 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
296 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
297 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
298 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
299 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
300};
301
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800302const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700303 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
304 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700305 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
306 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700307 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700308 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700309 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
310 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
311 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
312 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
313 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
314 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
315 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
316 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700317 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
318 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700319 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800320 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700321
Eric Laurentb23d5282013-05-14 15:27:20 -0700322 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700323 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530324 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
325 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
326 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530327 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
328 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700329 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700330 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700331 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700332 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700333
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800334 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800335 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700336 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700337
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700338 [USECASE_VOICE2_CALL] = "voice2-call",
339 [USECASE_VOLTE_CALL] = "volte-call",
340 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800341 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800342 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
343 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800344 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700345 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
346 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
347 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800348 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
349 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
350 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
351
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700352 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
353 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700354 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
355 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700356
357 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
358 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530359 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700360
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530361 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530362 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
363 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700364
365 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
366 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530367 /* For Interactive Audio Streams */
368 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
369 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
370 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
371 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
372 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
373 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
374 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
375 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700376
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800377 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
378
379 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback"
Eric Laurentb23d5282013-05-14 15:27:20 -0700380};
381
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700382static const audio_usecase_t offload_usecases[] = {
383 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700384 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
385 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
386 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
387 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
388 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
389 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
390 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
391 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700392};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800393
Varun Balaraje49253e2017-07-06 19:48:56 +0530394static const audio_usecase_t interactive_usecases[] = {
395 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
396 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
397 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
398 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
399 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
400 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
401 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
402 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
403};
404
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800405#define STRING_TO_ENUM(string) { #string, string }
406
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800407struct string_to_enum {
408 const char *name;
409 uint32_t value;
410};
411
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700412static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800413 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800414 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
415 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
416 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700417 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800418 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
419 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800420 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700421 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
422 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
423 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
424 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
425 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
426 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
427 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
428 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
429 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
430 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
431 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800432};
433
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700434static const struct string_to_enum formats_name_to_enum_table[] = {
435 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
436 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
437 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700438 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
439 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
440 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700441 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800442 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
443 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700444 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800445};
446
447//list of all supported sample rates by HDMI specification.
448static const int out_hdmi_sample_rates[] = {
449 32000, 44100, 48000, 88200, 96000, 176400, 192000,
450};
451
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700452static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800453 STRING_TO_ENUM(32000),
454 STRING_TO_ENUM(44100),
455 STRING_TO_ENUM(48000),
456 STRING_TO_ENUM(88200),
457 STRING_TO_ENUM(96000),
458 STRING_TO_ENUM(176400),
459 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700460};
461
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700462static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700463static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700464static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700465//cache last MBDRC cal step level
466static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700467
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530468static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
469static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800470static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530471static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530472
Vatsal Buchac09ae062018-11-14 13:25:08 +0530473#ifdef AUDIO_FEATURE_ENABLED_GCOV
474extern void __gcov_flush();
475static void enable_gcov()
476{
477 __gcov_flush();
478}
479#else
480static void enable_gcov()
481{
482}
483#endif
484
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700485static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
486 int flags __unused)
487{
488 int dir = 0;
489 switch (uc_id) {
490 case USECASE_AUDIO_RECORD_LOW_LATENCY:
491 dir = 1;
492 case USECASE_AUDIO_PLAYBACK_ULL:
493 break;
494 default:
495 return false;
496 }
497
498 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
499 PCM_PLAYBACK : PCM_CAPTURE);
500 if (adev->adm_is_noirq_avail)
501 return adev->adm_is_noirq_avail(adev->adm_data,
502 adev->snd_card, dev_id, dir);
503 return false;
504}
505
506static void register_out_stream(struct stream_out *out)
507{
508 struct audio_device *adev = out->dev;
509 if (is_offload_usecase(out->usecase) ||
510 !adev->adm_register_output_stream)
511 return;
512
513 // register stream first for backward compatibility
514 adev->adm_register_output_stream(adev->adm_data,
515 out->handle,
516 out->flags);
517
518 if (!adev->adm_set_config)
519 return;
520
521 if (out->realtime)
522 adev->adm_set_config(adev->adm_data,
523 out->handle,
524 out->pcm, &out->config);
525}
526
527static void register_in_stream(struct stream_in *in)
528{
529 struct audio_device *adev = in->dev;
530 if (!adev->adm_register_input_stream)
531 return;
532
533 adev->adm_register_input_stream(adev->adm_data,
534 in->capture_handle,
535 in->flags);
536
537 if (!adev->adm_set_config)
538 return;
539
540 if (in->realtime)
541 adev->adm_set_config(adev->adm_data,
542 in->capture_handle,
543 in->pcm,
544 &in->config);
545}
546
547static void request_out_focus(struct stream_out *out, long ns)
548{
549 struct audio_device *adev = out->dev;
550
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700551 if (adev->adm_request_focus_v2)
552 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
553 else if (adev->adm_request_focus)
554 adev->adm_request_focus(adev->adm_data, out->handle);
555}
556
557static void request_in_focus(struct stream_in *in, long ns)
558{
559 struct audio_device *adev = in->dev;
560
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700561 if (adev->adm_request_focus_v2)
562 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
563 else if (adev->adm_request_focus)
564 adev->adm_request_focus(adev->adm_data, in->capture_handle);
565}
566
567static void release_out_focus(struct stream_out *out)
568{
569 struct audio_device *adev = out->dev;
570
571 if (adev->adm_abandon_focus)
572 adev->adm_abandon_focus(adev->adm_data, out->handle);
573}
574
575static void release_in_focus(struct stream_in *in)
576{
577 struct audio_device *adev = in->dev;
578 if (adev->adm_abandon_focus)
579 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
580}
581
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530582static int parse_snd_card_status(struct str_parms *parms, int *card,
583 card_status_t *status)
584{
585 char value[32]={0};
586 char state[32]={0};
587
588 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
589 if (ret < 0)
590 return -1;
591
592 // sscanf should be okay as value is of max length 32.
593 // same as sizeof state.
594 if (sscanf(value, "%d,%s", card, state) < 2)
595 return -1;
596
597 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
598 CARD_STATUS_OFFLINE;
599 return 0;
600}
601
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700602static inline void adjust_frames_for_device_delay(struct stream_out *out,
603 uint32_t *dsp_frames) {
604 // Adjustment accounts for A2dp encoder latency with offload usecases
605 // Note: Encoder latency is returned in ms.
606 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
607 unsigned long offset =
608 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
609 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
610 }
611}
612
vivek mehtaa76401a2015-04-24 14:12:15 -0700613__attribute__ ((visibility ("default")))
614bool audio_hw_send_gain_dep_calibration(int level) {
615 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700616 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700617
618 pthread_mutex_lock(&adev_init_lock);
619
620 if (adev != NULL && adev->platform != NULL) {
621 pthread_mutex_lock(&adev->lock);
622 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700623
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530624 // cache level info for any of the use case which
625 // was not started.
626 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700627
vivek mehtaa76401a2015-04-24 14:12:15 -0700628 pthread_mutex_unlock(&adev->lock);
629 } else {
630 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
631 }
632
633 pthread_mutex_unlock(&adev_init_lock);
634
635 return ret_val;
636}
637
Ashish Jain5106d362016-05-11 19:23:33 +0530638static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
639{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800640 bool gapless_enabled = false;
641 const char *mixer_ctl_name = "Compress Gapless Playback";
642 struct mixer_ctl *ctl;
643
644 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700645 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530646
647 /*Disable gapless if its AV playback*/
648 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800649
650 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
651 if (!ctl) {
652 ALOGE("%s: Could not get ctl for mixer cmd - %s",
653 __func__, mixer_ctl_name);
654 return -EINVAL;
655 }
656
657 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
658 ALOGE("%s: Could not set gapless mode %d",
659 __func__, gapless_enabled);
660 return -EINVAL;
661 }
662 return 0;
663}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700664
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700665__attribute__ ((visibility ("default")))
666int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
667 int table_size) {
668 int ret_val = 0;
669 ALOGV("%s: enter ... ", __func__);
670
671 pthread_mutex_lock(&adev_init_lock);
672 if (adev == NULL) {
673 ALOGW("%s: adev is NULL .... ", __func__);
674 goto done;
675 }
676
677 pthread_mutex_lock(&adev->lock);
678 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
679 pthread_mutex_unlock(&adev->lock);
680done:
681 pthread_mutex_unlock(&adev_init_lock);
682 ALOGV("%s: exit ... ", __func__);
683 return ret_val;
684}
685
Aalique Grahame22e49102018-12-18 14:23:57 -0800686#ifdef MAXXAUDIO_QDSP_ENABLED
687bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
688{
689 bool ret = false;
690 ALOGV("%s: enter ...", __func__);
691
692 pthread_mutex_lock(&adev_init_lock);
693
694 if (adev != NULL && adev->platform != NULL) {
695 pthread_mutex_lock(&adev->lock);
696 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
697 pthread_mutex_unlock(&adev->lock);
698 }
699
700 pthread_mutex_unlock(&adev_init_lock);
701
702 ALOGV("%s: exit with ret %d", __func__, ret);
703 return ret;
704}
705#else
706#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
707#endif
708
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700709static bool is_supported_format(audio_format_t format)
710{
Eric Laurent86e17132013-09-12 17:49:30 -0700711 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530712 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530713 format == AUDIO_FORMAT_AAC_LC ||
714 format == AUDIO_FORMAT_AAC_HE_V1 ||
715 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530716 format == AUDIO_FORMAT_AAC_ADTS_LC ||
717 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
718 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530719 format == AUDIO_FORMAT_AAC_LATM_LC ||
720 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
721 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530722 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
723 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530724 format == AUDIO_FORMAT_PCM_FLOAT ||
725 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700726 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530727 format == AUDIO_FORMAT_AC3 ||
728 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700729 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530730 format == AUDIO_FORMAT_DTS ||
731 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800732 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530733 format == AUDIO_FORMAT_ALAC ||
734 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530735 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530736 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800737 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530738 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700739 format == AUDIO_FORMAT_APTX ||
740 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800741 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700742
743 return false;
744}
745
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700746static inline bool is_mmap_usecase(audio_usecase_t uc_id)
747{
748 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
749 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
750}
751
Avinash Vaish71a8b972014-07-24 15:36:33 +0530752static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
753 struct audio_usecase *uc_info)
754{
755 struct listnode *node;
756 struct audio_usecase *usecase;
757
758 if (uc_info == NULL)
759 return -EINVAL;
760
761 /* Re-route all voice usecases on the shared backend other than the
762 specified usecase to new snd devices */
763 list_for_each(node, &adev->usecase_list) {
764 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800765 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530766 enable_audio_route(adev, usecase);
767 }
768 return 0;
769}
770
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530771static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530772{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530773 ALOGV("%s", __func__);
774 audio_route_apply_and_update_path(adev->audio_route,
775 "asrc-mode");
776 adev->asrc_mode_enabled = true;
777}
778
779static void disable_asrc_mode(struct audio_device *adev)
780{
781 ALOGV("%s", __func__);
782 audio_route_reset_and_update_path(adev->audio_route,
783 "asrc-mode");
784 adev->asrc_mode_enabled = false;
785}
786
787/*
788 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
789 * 44.1 or Native DSD backends are enabled for any of current use case.
790 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
791 * - Disable current mix path use case(Headphone backend) and re-enable it with
792 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
793 * e.g. Naitve DSD or Headphone 44.1 -> + 48
794 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530795static void check_and_set_asrc_mode(struct audio_device *adev,
796 struct audio_usecase *uc_info,
797 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530798{
799 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530800 int i, num_new_devices = 0;
801 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
802 /*
803 *Split snd device for new combo use case
804 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
805 */
806 if (platform_split_snd_device(adev->platform,
807 snd_device,
808 &num_new_devices,
809 split_new_snd_devices) == 0) {
810 for (i = 0; i < num_new_devices; i++)
811 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
812 } else {
813 int new_backend_idx = platform_get_backend_index(snd_device);
814 if (((new_backend_idx == HEADPHONE_BACKEND) ||
815 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
816 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
817 !adev->asrc_mode_enabled) {
818 struct listnode *node = NULL;
819 struct audio_usecase *uc = NULL;
820 struct stream_out *curr_out = NULL;
821 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
822 int i, num_devices, ret = 0;
823 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530824
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530825 list_for_each(node, &adev->usecase_list) {
826 uc = node_to_item(node, struct audio_usecase, list);
827 curr_out = (struct stream_out*) uc->stream.out;
828 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
829 /*
830 *Split snd device for existing combo use case
831 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
832 */
833 ret = platform_split_snd_device(adev->platform,
834 uc->out_snd_device,
835 &num_devices,
836 split_snd_devices);
837 if (ret < 0 || num_devices == 0) {
838 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
839 split_snd_devices[0] = uc->out_snd_device;
840 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800841 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530842 for (i = 0; i < num_devices; i++) {
843 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
844 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
845 if((new_backend_idx == HEADPHONE_BACKEND) &&
846 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
847 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
848 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
849 __func__);
850 enable_asrc_mode(adev);
851 break;
852 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
853 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
854 (usecase_backend_idx == HEADPHONE_BACKEND)) {
855 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
856 __func__);
857 disable_audio_route(adev, uc);
858 disable_snd_device(adev, uc->out_snd_device);
859 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
860 if (new_backend_idx == DSD_NATIVE_BACKEND)
861 audio_route_apply_and_update_path(adev->audio_route,
862 "hph-true-highquality-mode");
863 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
864 (curr_out->bit_width >= 24))
865 audio_route_apply_and_update_path(adev->audio_route,
866 "hph-highquality-mode");
867 enable_asrc_mode(adev);
868 enable_snd_device(adev, uc->out_snd_device);
869 enable_audio_route(adev, uc);
870 break;
871 }
872 }
873 // reset split devices count
874 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800875 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530876 if (adev->asrc_mode_enabled)
877 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530878 }
879 }
880 }
881}
882
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700883#ifdef DYNAMIC_ECNS_ENABLED
884static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
885 struct audio_effect_config effect_config,
886 unsigned int param_value)
887{
888 char mixer_ctl_name[] = "Audio Effect";
889 struct mixer_ctl *ctl;
890 long set_values[6];
891 struct stream_in *in = adev->active_input;
892
893 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
894 if (!ctl) {
895 ALOGE("%s: Could not get mixer ctl - %s",
896 __func__, mixer_ctl_name);
897 return -EINVAL;
898 }
899
900 set_values[0] = 1; //0:Rx 1:Tx
901 set_values[1] = in->app_type_cfg.app_type;
902 set_values[2] = (long)effect_config.module_id;
903 set_values[3] = (long)effect_config.instance_id;
904 set_values[4] = (long)effect_config.param_id;
905 set_values[5] = param_value;
906
907 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
908
909 return 0;
910
911}
912
913static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
914 int effect_type, unsigned int *param_value)
915{
916 int ret = 0;
917 struct audio_effect_config other_effect_config;
918 struct audio_usecase *usecase = NULL;
919 struct stream_in *in = adev->active_input;
920
921 usecase = get_usecase_from_list(adev, in->usecase);
922 if (!usecase)
923 return -EINVAL;
924
925 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
926 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
927 if (ret < 0) {
928 ALOGE("%s Failed to get effect params %d", __func__, ret);
929 return ret;
930 }
931
932 if (module_id == other_effect_config.module_id) {
933 //Same module id for AEC/NS. Values need to be combined
934 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
935 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
936 *param_value |= other_effect_config.param_value;
937 }
938 }
939
940 return ret;
941}
942
943static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
944{
945 struct audio_effect_config effect_config;
946 struct audio_usecase *usecase = NULL;
947 int ret = 0;
948 unsigned int param_value = 0;
949 struct stream_in *in = adev->active_input;
950
951 if (!in) {
952 ALOGE("%s: Invalid input stream", __func__);
953 return -EINVAL;
954 }
955
956 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
957
958 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800959 if (usecase == NULL) {
960 ALOGE("%s: Could not find the usecase (%d) in the list",
961 __func__, in->usecase);
962 return -EINVAL;
963 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700964
965 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
966 if (ret < 0) {
967 ALOGE("%s Failed to get module id %d", __func__, ret);
968 return ret;
969 }
970 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
971 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
972
973 if(enable)
974 param_value = effect_config.param_value;
975
976 /*Special handling for AEC & NS effects Param values need to be
977 updated if module ids are same*/
978
979 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
980 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
981 if (ret < 0)
982 return ret;
983 }
984
985 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
986
987 return ret;
988}
989
990static void check_and_enable_effect(struct audio_device *adev)
991{
992
993 if (adev->active_input->enable_aec) {
994 enable_disable_effect(adev, EFFECT_AEC, true);
995 }
996
997 if (adev->active_input->enable_ns &&
998 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
999 enable_disable_effect(adev, EFFECT_NS, true);
1000 }
1001}
1002#else
1003#define enable_disable_effect(x, y, z) ENOSYS
1004#define check_and_enable_effect(x) ENOSYS
1005#endif
1006
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001007int pcm_ioctl(struct pcm *pcm, int request, ...)
1008{
1009 va_list ap;
1010 void * arg;
1011 int pcm_fd = *(int*)pcm;
1012
1013 va_start(ap, request);
1014 arg = va_arg(ap, void *);
1015 va_end(ap);
1016
1017 return ioctl(pcm_fd, request, arg);
1018}
1019
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001020int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001021 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001023 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001024 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301025 struct stream_out *out = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301026 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001027
1028 if (usecase == NULL)
1029 return -EINVAL;
1030
1031 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1032
Surendar Karka93cd25a2018-08-28 14:21:37 +05301033 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001034 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001035 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001036 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001037
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001038#ifdef DS1_DOLBY_DAP_ENABLED
1039 audio_extn_dolby_set_dmid(adev);
1040 audio_extn_dolby_set_endpoint(adev);
1041#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001042 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001043 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301044 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001045 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301046 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301047 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1048 out = usecase->stream.out;
1049 if (out && out->compr)
1050 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1051 }
1052
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001053 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001054 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001055 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301056 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1057 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1058 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1059 if (parms) {
1060 audio_extn_fm_set_parameters(adev, parms);
1061 str_parms_destroy(parms);
1062 }
1063 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001064 ALOGV("%s: exit", __func__);
1065 return 0;
1066}
1067
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001068int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001069 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001070{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001071 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001072 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001073
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301074 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001075 return -EINVAL;
1076
1077 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301078 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001079 snd_device = usecase->in_snd_device;
1080 else
1081 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001082 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001083 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001084 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001085 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001086 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301087 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001088 ALOGV("%s: exit", __func__);
1089 return 0;
1090}
1091
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001092int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001093 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001094{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301095 int i, num_devices = 0;
1096 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001097 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1098
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001099 if (snd_device < SND_DEVICE_MIN ||
1100 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001101 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001102 return -EINVAL;
1103 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001104
1105 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001106
1107 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
1108 ALOGE("%s: Invalid sound device returned", __func__);
1109 return -EINVAL;
1110 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001111 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -07001112 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001113 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001114 return 0;
1115 }
1116
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301117
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001118 if (audio_extn_spkr_prot_is_enabled())
1119 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001120
Aalique Grahame22e49102018-12-18 14:23:57 -08001121 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1122
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001123 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1124 audio_extn_spkr_prot_is_enabled()) {
1125 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001126 adev->snd_dev_ref_cnt[snd_device]--;
1127 return -EINVAL;
1128 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001129 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001130 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001131 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001132 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001133 return -EINVAL;
1134 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001135 } else if (platform_split_snd_device(adev->platform,
1136 snd_device,
1137 &num_devices,
1138 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301139 for (i = 0; i < num_devices; i++) {
1140 enable_snd_device(adev, new_snd_devices[i]);
1141 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001142 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001143 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001144 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301145
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301146
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301147 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1148 (audio_extn_a2dp_start_playback() < 0)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02001149 ALOGE(" fail to configure A2dp Source control path ");
1150 return -EINVAL;
1151 }
1152
1153 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1154 (audio_extn_a2dp_start_capture() < 0)) {
1155 ALOGE(" fail to configure A2dp Sink control path ");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301156 return -EINVAL;
1157 }
1158
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001159 /* due to the possibility of calibration overwrite between listen
1160 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001161 audio_extn_sound_trigger_update_device_status(snd_device,
1162 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301163 audio_extn_listen_update_device_status(snd_device,
1164 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001165 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001166 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001167 audio_extn_sound_trigger_update_device_status(snd_device,
1168 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301169 audio_extn_listen_update_device_status(snd_device,
1170 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001171 return -EINVAL;
1172 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001173 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001174 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301175
1176 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1177 !adev->native_playback_enabled &&
1178 audio_is_true_native_stream_active(adev)) {
1179 ALOGD("%s: %d: napb: enabling native mode in hardware",
1180 __func__, __LINE__);
1181 audio_route_apply_and_update_path(adev->audio_route,
1182 "true-native-mode");
1183 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301184 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301185 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1186 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001187 (audio_extn_ffv_get_stream() == adev->active_input)) {
1188 ALOGD("%s: init ec ref loopback", __func__);
1189 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1190 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001191 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001192 return 0;
1193}
1194
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001195int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001196 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001197{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301198 int i, num_devices = 0;
1199 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001200 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1201
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001202 if (snd_device < SND_DEVICE_MIN ||
1203 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001204 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001205 return -EINVAL;
1206 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001207 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1208 ALOGE("%s: device ref cnt is already 0", __func__);
1209 return -EINVAL;
1210 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001211
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001212 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001213
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001214 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1215 ALOGE("%s: Invalid sound device returned", __func__);
1216 return -EINVAL;
1217 }
1218
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001219 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001220 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301221
Aalique Grahame22e49102018-12-18 14:23:57 -08001222 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1223
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001224 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1225 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001226 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001227
1228 // when speaker device is disabled, reset swap.
1229 // will be renabled on usecase start
1230 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001231 } else if (platform_split_snd_device(adev->platform,
1232 snd_device,
1233 &num_devices,
1234 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301235 for (i = 0; i < num_devices; i++) {
1236 disable_snd_device(adev, new_snd_devices[i]);
1237 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001238 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001239 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001240 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001241 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001242
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301243 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1244 audio_extn_a2dp_stop_playback();
1245
Florian Pfister1a84f312018-07-19 14:38:18 +02001246 if (SND_DEVICE_IN_BT_A2DP == snd_device)
1247 audio_extn_a2dp_stop_capture();
1248
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001249 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301250 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301251 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1252 adev->native_playback_enabled) {
1253 ALOGD("%s: %d: napb: disabling native mode in hardware",
1254 __func__, __LINE__);
1255 audio_route_reset_and_update_path(adev->audio_route,
1256 "true-native-mode");
1257 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301258 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1259 adev->asrc_mode_enabled) {
1260 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301261 disable_asrc_mode(adev);
1262 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301263 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001264 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1265 (audio_extn_ffv_get_stream() == adev->active_input)) {
1266 ALOGD("%s: deinit ec ref loopback", __func__);
1267 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1268 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001269 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001270 audio_extn_sound_trigger_update_device_status(snd_device,
1271 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301272 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001273 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001274 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001275
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001276 return 0;
1277}
1278
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001279/*
1280 legend:
1281 uc - existing usecase
1282 new_uc - new usecase
1283 d1, d11, d2 - SND_DEVICE enums
1284 a1, a2 - corresponding ANDROID device enums
1285 B1, B2 - backend strings
1286
1287case 1
1288 uc->dev d1 (a1) B1
1289 new_uc->dev d1 (a1), d2 (a2) B1, B2
1290
1291 resolution: disable and enable uc->dev on d1
1292
1293case 2
1294 uc->dev d1 (a1) B1
1295 new_uc->dev d11 (a1) B1
1296
1297 resolution: need to switch uc since d1 and d11 are related
1298 (e.g. speaker and voice-speaker)
1299 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1300
1301case 3
1302 uc->dev d1 (a1) B1
1303 new_uc->dev d2 (a2) B2
1304
1305 resolution: no need to switch uc
1306
1307case 4
1308 uc->dev d1 (a1) B1
1309 new_uc->dev d2 (a2) B1
1310
1311 resolution: disable enable uc-dev on d2 since backends match
1312 we cannot enable two streams on two different devices if they
1313 share the same backend. e.g. if offload is on speaker device using
1314 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1315 using the same backend, offload must also be switched to voice-handset.
1316
1317case 5
1318 uc->dev d1 (a1) B1
1319 new_uc->dev d1 (a1), d2 (a2) B1
1320
1321 resolution: disable enable uc-dev on d2 since backends match
1322 we cannot enable two streams on two different devices if they
1323 share the same backend.
1324
1325case 6
1326 uc->dev d1 (a1) B1
1327 new_uc->dev d2 (a1) B2
1328
1329 resolution: no need to switch
1330
1331case 7
1332 uc->dev d1 (a1), d2 (a2) B1, B2
1333 new_uc->dev d1 (a1) B1
1334
1335 resolution: no need to switch
1336
Zhou Song4ba65882018-07-09 14:48:07 +08001337case 8
1338 uc->dev d1 (a1) B1
1339 new_uc->dev d11 (a1), d2 (a2) B1, B2
1340 resolution: compared to case 1, for this case, d1 and d11 are related
1341 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001342*/
1343static snd_device_t derive_playback_snd_device(void * platform,
1344 struct audio_usecase *uc,
1345 struct audio_usecase *new_uc,
1346 snd_device_t new_snd_device)
1347{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301348 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001349
1350 snd_device_t d1 = uc->out_snd_device;
1351 snd_device_t d2 = new_snd_device;
1352
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301353 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301354 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301355 a1 = uc->stream.inout->out_config.devices;
1356 a2 = new_uc->stream.inout->out_config.devices;
1357 break;
1358 default :
1359 a1 = uc->stream.out->devices;
1360 a2 = new_uc->stream.out->devices;
1361 break;
1362 }
1363
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001364 // Treat as a special case when a1 and a2 are not disjoint
1365 if ((a1 != a2) && (a1 & a2)) {
1366 snd_device_t d3[2];
1367 int num_devices = 0;
1368 int ret = platform_split_snd_device(platform,
1369 popcount(a1) > 1 ? d1 : d2,
1370 &num_devices,
1371 d3);
1372 if (ret < 0) {
1373 if (ret != -ENOSYS) {
1374 ALOGW("%s failed to split snd_device %d",
1375 __func__,
1376 popcount(a1) > 1 ? d1 : d2);
1377 }
1378 goto end;
1379 }
1380
1381 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1382 // But if it does happen, we need to give priority to d2 if
1383 // the combo devices active on the existing usecase share a backend.
1384 // This is because we cannot have a usecase active on a combo device
1385 // and a new usecase requests one device in this combo pair.
1386 if (platform_check_backends_match(d3[0], d3[1])) {
1387 return d2; // case 5
1388 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001389 // check if d1 is related to any of d3's
1390 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001391 return d1; // case 1
1392 else
1393 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001394 }
1395 } else {
1396 if (platform_check_backends_match(d1, d2)) {
1397 return d2; // case 2, 4
1398 } else {
1399 return d1; // case 6, 3
1400 }
1401 }
1402
1403end:
1404 return d2; // return whatever was calculated before.
1405}
1406
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001407static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301408 struct audio_usecase *uc_info,
1409 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001410{
1411 struct listnode *node;
1412 struct audio_usecase *usecase;
1413 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301414 snd_device_t uc_derive_snd_device;
1415 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001416 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001417 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301418 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001419 /*
1420 * This function is to make sure that all the usecases that are active on
1421 * the hardware codec backend are always routed to any one device that is
1422 * handled by the hardware codec.
1423 * For example, if low-latency and deep-buffer usecases are currently active
1424 * on speaker and out_set_parameters(headset) is received on low-latency
1425 * output, then we have to make sure deep-buffer is also switched to headset,
1426 * because of the limitation that both the devices cannot be enabled
1427 * at the same time as they share the same backend.
1428 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001429 /*
1430 * This call is to check if we need to force routing for a particular stream
1431 * If there is a backend configuration change for the device when a
1432 * new stream starts, then ADM needs to be closed and re-opened with the new
1433 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001434 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001435 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001436 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1437 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301438 /* For a2dp device reconfigure all active sessions
1439 * with new AFE encoder format based on a2dp state
1440 */
1441 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1442 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1443 audio_extn_a2dp_is_force_device_switch()) {
1444 force_routing = true;
1445 force_restart_session = true;
1446 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301447 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1448
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001449 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001450 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001451 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001452 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1453 switch_device[i] = false;
1454
1455 list_for_each(node, &adev->usecase_list) {
1456 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001457
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301458 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1459 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301460 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301461 platform_get_snd_device_name(usecase->out_snd_device),
1462 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301463 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1464 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1465 usecase, uc_info, snd_device);
1466 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1467 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1468 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1469 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001470 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301471 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1472 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1473 ((force_restart_session) ||
1474 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301475 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1476 __func__, use_case_table[usecase->id],
1477 platform_get_snd_device_name(usecase->out_snd_device));
1478 disable_audio_route(adev, usecase);
1479 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301480 /* Enable existing usecase on derived playback device */
1481 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301482 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301483 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001484 }
1485 }
1486
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301487 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1488 num_uc_to_switch);
1489
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001490 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001491 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001492
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301493 /* Make sure the previous devices to be disabled first and then enable the
1494 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001495 list_for_each(node, &adev->usecase_list) {
1496 usecase = node_to_item(node, struct audio_usecase, list);
1497 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001498 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001499 }
1500 }
1501
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001502 list_for_each(node, &adev->usecase_list) {
1503 usecase = node_to_item(node, struct audio_usecase, list);
1504 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301505 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001506 }
1507 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001508
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001509 /* Re-route all the usecases on the shared backend other than the
1510 specified usecase to new snd devices */
1511 list_for_each(node, &adev->usecase_list) {
1512 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301513 /* Update the out_snd_device only before enabling the audio route */
1514 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301515 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301516 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301517 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301518 use_case_table[usecase->id],
1519 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001520 /* Update voc calibration before enabling VoIP route */
1521 if (usecase->type == VOIP_CALL)
1522 status = platform_switch_voice_call_device_post(adev->platform,
1523 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001524 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301525 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001526 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1527 out_set_voip_volume(&usecase->stream.out->stream,
1528 usecase->stream.out->volume_l,
1529 usecase->stream.out->volume_r);
1530 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301531 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001532 }
1533 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001534 }
1535}
1536
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301537static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001538 struct audio_usecase *uc_info,
1539 snd_device_t snd_device)
1540{
1541 struct listnode *node;
1542 struct audio_usecase *usecase;
1543 bool switch_device[AUDIO_USECASE_MAX];
1544 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301545 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001546 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001547
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301548 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1549 snd_device);
1550 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301551
1552 /*
1553 * Make sure out devices is checked against out codec backend device and
1554 * also in devices against in codec backend. Checking out device against in
1555 * codec backend or vice versa causes issues.
1556 */
1557 if (uc_info->type == PCM_CAPTURE)
1558 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001559 /*
1560 * This function is to make sure that all the active capture usecases
1561 * are always routed to the same input sound device.
1562 * For example, if audio-record and voice-call usecases are currently
1563 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1564 * is received for voice call then we have to make sure that audio-record
1565 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1566 * because of the limitation that two devices cannot be enabled
1567 * at the same time if they share the same backend.
1568 */
1569 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1570 switch_device[i] = false;
1571
1572 list_for_each(node, &adev->usecase_list) {
1573 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301574 /*
1575 * TODO: Enhance below condition to handle BT sco/USB multi recording
1576 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001577 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001578 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301579 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301580 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301581 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301582 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001583 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001584 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1585 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001586 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001587 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001588 switch_device[usecase->id] = true;
1589 num_uc_to_switch++;
1590 }
1591 }
1592
1593 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001594 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001595
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301596 /* Make sure the previous devices to be disabled first and then enable the
1597 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001598 list_for_each(node, &adev->usecase_list) {
1599 usecase = node_to_item(node, struct audio_usecase, list);
1600 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001601 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001602 }
1603 }
1604
1605 list_for_each(node, &adev->usecase_list) {
1606 usecase = node_to_item(node, struct audio_usecase, list);
1607 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001608 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001609 }
1610 }
1611
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001612 /* Re-route all the usecases on the shared backend other than the
1613 specified usecase to new snd devices */
1614 list_for_each(node, &adev->usecase_list) {
1615 usecase = node_to_item(node, struct audio_usecase, list);
1616 /* Update the in_snd_device only before enabling the audio route */
1617 if (switch_device[usecase->id] ) {
1618 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001619 if (usecase->type != VOICE_CALL) {
1620 /* Update voc calibration before enabling VoIP route */
1621 if (usecase->type == VOIP_CALL)
1622 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001623 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001624 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301625 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001626 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001627 }
1628 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001629 }
1630}
1631
Mingming Yin3a941d42016-02-17 18:08:05 -08001632static void reset_hdmi_sink_caps(struct stream_out *out) {
1633 int i = 0;
1634
1635 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1636 out->supported_channel_masks[i] = 0;
1637 }
1638 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1639 out->supported_formats[i] = 0;
1640 }
1641 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1642 out->supported_sample_rates[i] = 0;
1643 }
1644}
1645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001647static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001648{
Mingming Yin3a941d42016-02-17 18:08:05 -08001649 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001650 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001651
Mingming Yin3a941d42016-02-17 18:08:05 -08001652 reset_hdmi_sink_caps(out);
1653
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001654 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001655 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001656 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001657 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001658 }
1659
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001662 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001663 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001664 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1665 case 6:
1666 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1667 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1668 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1669 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1670 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1671 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672 break;
1673 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001674 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001675 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001676 break;
1677 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001678
1679 // check channel format caps
1680 i = 0;
1681 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1682 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1683 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1684 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1685 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1686 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1687 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1688 }
1689
Ben Romberger1aaaf862017-04-06 17:49:46 -07001690 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1691 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1692 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1693 }
1694
Mingming Yin3a941d42016-02-17 18:08:05 -08001695 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1696 ALOGV(":%s HDMI supports DTS format", __func__);
1697 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1698 }
1699
1700 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1701 ALOGV(":%s HDMI supports DTS HD format", __func__);
1702 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1703 }
1704
Naresh Tanniru928f0862017-04-07 16:44:23 -07001705 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1706 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1707 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1708 }
1709
Mingming Yin3a941d42016-02-17 18:08:05 -08001710
1711 // check sample rate caps
1712 i = 0;
1713 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1714 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1715 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1716 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1717 }
1718 }
1719
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001720 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001721}
1722
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001723static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1724 uint32_t *supported_sample_rates __unused,
1725 uint32_t max_rates __unused)
1726{
1727 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1728 supported_sample_rates,
1729 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301730 ssize_t i = 0;
1731
1732 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001733 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1734 supported_sample_rates[i]);
1735 }
1736 return count;
1737}
1738
1739static inline int read_usb_sup_channel_masks(bool is_playback,
1740 audio_channel_mask_t *supported_channel_masks,
1741 uint32_t max_masks)
1742{
1743 int channels = audio_extn_usb_get_max_channels(is_playback);
1744 int channel_count;
1745 uint32_t num_masks = 0;
1746 if (channels > MAX_HIFI_CHANNEL_COUNT)
1747 channels = MAX_HIFI_CHANNEL_COUNT;
1748
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301749 channel_count = DEFAULT_CHANNEL_COUNT;
1750
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001751 if (is_playback) {
1752 // For playback we never report mono because the framework always outputs stereo
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001753 // audio_channel_out_mask_from_count() does return positional masks for channel counts
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301754 // above 2 but we want indexed masks here.
1755 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001756 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001757 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1758 // indexed mask
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301759 supported_channel_masks[num_masks++] = audio_channel_in_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001760 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301761
1762 for (channel_count = channels; ((channel_count >= DEFAULT_CHANNEL_COUNT) &&
1763 (num_masks < max_masks)); channel_count--) {
1764 supported_channel_masks[num_masks++] =
1765 audio_channel_mask_for_index_assignment_from_count(channel_count);
1766 }
1767
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001768 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1769 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1770 return num_masks;
1771}
1772
1773static inline int read_usb_sup_formats(bool is_playback __unused,
1774 audio_format_t *supported_formats,
1775 uint32_t max_formats __unused)
1776{
1777 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1778 switch (bitwidth) {
1779 case 24:
1780 // XXX : usb.c returns 24 for s24 and s24_le?
1781 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1782 break;
1783 case 32:
1784 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1785 break;
1786 case 16:
1787 default :
1788 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1789 break;
1790 }
1791 ALOGV("%s: %s supported format %d", __func__,
1792 is_playback ? "P" : "C", bitwidth);
1793 return 1;
1794}
1795
1796static inline int read_usb_sup_params_and_compare(bool is_playback,
1797 audio_format_t *format,
1798 audio_format_t *supported_formats,
1799 uint32_t max_formats,
1800 audio_channel_mask_t *mask,
1801 audio_channel_mask_t *supported_channel_masks,
1802 uint32_t max_masks,
1803 uint32_t *rate,
1804 uint32_t *supported_sample_rates,
1805 uint32_t max_rates) {
1806 int ret = 0;
1807 int num_formats;
1808 int num_masks;
1809 int num_rates;
1810 int i;
1811
1812 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1813 max_formats);
1814 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1815 max_masks);
1816
1817 num_rates = read_usb_sup_sample_rates(is_playback,
1818 supported_sample_rates, max_rates);
1819
1820#define LUT(table, len, what, dflt) \
1821 for (i=0; i<len && (table[i] != what); i++); \
1822 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1823
1824 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1825 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1826 LUT(supported_sample_rates, num_rates, *rate, 0);
1827
1828#undef LUT
1829 return ret < 0 ? -EINVAL : 0; // HACK TBD
1830}
1831
Alexy Josephb1379942016-01-29 15:49:38 -08001832audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001833 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001834{
1835 struct audio_usecase *usecase;
1836 struct listnode *node;
1837
1838 list_for_each(node, &adev->usecase_list) {
1839 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001840 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001841 ALOGV("%s: usecase id %d", __func__, usecase->id);
1842 return usecase->id;
1843 }
1844 }
1845 return USECASE_INVALID;
1846}
1847
Alexy Josephb1379942016-01-29 15:49:38 -08001848struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001849 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001850{
1851 struct audio_usecase *usecase;
1852 struct listnode *node;
1853
1854 list_for_each(node, &adev->usecase_list) {
1855 usecase = node_to_item(node, struct audio_usecase, list);
1856 if (usecase->id == uc_id)
1857 return usecase;
1858 }
1859 return NULL;
1860}
1861
Dhananjay Kumard4833242016-10-06 22:09:12 +05301862struct stream_in *get_next_active_input(const struct audio_device *adev)
1863{
1864 struct audio_usecase *usecase;
1865 struct listnode *node;
1866
1867 list_for_each_reverse(node, &adev->usecase_list) {
1868 usecase = node_to_item(node, struct audio_usecase, list);
1869 if (usecase->type == PCM_CAPTURE)
1870 return usecase->stream.in;
1871 }
1872 return NULL;
1873}
1874
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301875/*
1876 * is a true native playback active
1877 */
1878bool audio_is_true_native_stream_active(struct audio_device *adev)
1879{
1880 bool active = false;
1881 int i = 0;
1882 struct listnode *node;
1883
1884 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1885 ALOGV("%s:napb: not in true mode or non hdphones device",
1886 __func__);
1887 active = false;
1888 goto exit;
1889 }
1890
1891 list_for_each(node, &adev->usecase_list) {
1892 struct audio_usecase *uc;
1893 uc = node_to_item(node, struct audio_usecase, list);
1894 struct stream_out *curr_out =
1895 (struct stream_out*) uc->stream.out;
1896
1897 if (curr_out && PCM_PLAYBACK == uc->type) {
1898 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1899 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1900 uc->id, curr_out->sample_rate,
1901 curr_out->bit_width,
1902 platform_get_snd_device_name(uc->out_snd_device));
1903
1904 if (is_offload_usecase(uc->id) &&
1905 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1906 active = true;
1907 ALOGD("%s:napb:native stream detected", __func__);
1908 }
1909 }
1910 }
1911exit:
1912 return active;
1913}
1914
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001915uint32_t adev_get_dsp_bit_width_enforce_mode()
1916{
1917 if (adev == NULL) {
1918 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1919 return 0;
1920 }
1921 return adev->dsp_bit_width_enforce_mode;
1922}
1923
1924static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1925{
1926 char value[PROPERTY_VALUE_MAX];
1927 int trial;
1928 uint32_t dsp_bit_width_enforce_mode = 0;
1929
1930 if (!mixer) {
1931 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1932 __func__);
1933 return 0;
1934 }
1935
1936 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1937 value, NULL) > 0) {
1938 trial = atoi(value);
1939 switch (trial) {
1940 case 16:
1941 dsp_bit_width_enforce_mode = 16;
1942 break;
1943 case 24:
1944 dsp_bit_width_enforce_mode = 24;
1945 break;
1946 case 32:
1947 dsp_bit_width_enforce_mode = 32;
1948 break;
1949 default:
1950 dsp_bit_width_enforce_mode = 0;
1951 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1952 break;
1953 }
1954 }
1955
1956 return dsp_bit_width_enforce_mode;
1957}
1958
1959static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1960 uint32_t enforce_mode,
1961 bool enable)
1962{
1963 struct mixer_ctl *ctl = NULL;
1964 const char *mixer_ctl_name = "ASM Bit Width";
1965 uint32_t asm_bit_width_mode = 0;
1966
1967 if (enforce_mode == 0) {
1968 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1969 return;
1970 }
1971
1972 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1973 if (!ctl) {
1974 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1975 __func__, mixer_ctl_name);
1976 return;
1977 }
1978
1979 if (enable)
1980 asm_bit_width_mode = enforce_mode;
1981 else
1982 asm_bit_width_mode = 0;
1983
1984 ALOGV("%s DSP bit width feature status is %d width=%d",
1985 __func__, enable, asm_bit_width_mode);
1986 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1987 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1988 asm_bit_width_mode);
1989
1990 return;
1991}
1992
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301993/*
1994 * if native DSD playback active
1995 */
1996bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1997{
1998 bool active = false;
1999 struct listnode *node = NULL;
2000 struct audio_usecase *uc = NULL;
2001 struct stream_out *curr_out = NULL;
2002
2003 list_for_each(node, &adev->usecase_list) {
2004 uc = node_to_item(node, struct audio_usecase, list);
2005 curr_out = (struct stream_out*) uc->stream.out;
2006
2007 if (curr_out && PCM_PLAYBACK == uc->type &&
2008 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2009 active = true;
2010 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302011 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302012 }
2013 }
2014 return active;
2015}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302016
2017static bool force_device_switch(struct audio_usecase *usecase)
2018{
2019 bool ret = false;
2020 bool is_it_true_mode = false;
2021
Zhou Song30f2c3e2018-02-08 14:02:15 +08002022 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302023 usecase->type == TRANSCODE_LOOPBACK_RX ||
2024 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002025 return false;
2026 }
2027
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002028 if(usecase->stream.out == NULL) {
2029 ALOGE("%s: stream.out is NULL", __func__);
2030 return false;
2031 }
2032
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302033 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002034 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2035 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2036 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302037 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2038 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2039 (!is_it_true_mode && adev->native_playback_enabled)){
2040 ret = true;
2041 ALOGD("napb: time to toggle native mode");
2042 }
2043 }
2044
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302045 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302046 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2047 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002048 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302049 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302050 ALOGD("Force a2dp device switch to update new encoder config");
2051 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002052 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302053
Florian Pfister1a84f312018-07-19 14:38:18 +02002054 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302055 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2056 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002057 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302058 return ret;
2059}
2060
Aalique Grahame22e49102018-12-18 14:23:57 -08002061static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2062{
2063 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2064}
2065
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302066bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2067{
2068 bool ret=false;
2069 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2070 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2071 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2072 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2073 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2074 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2075 ret = true;
2076
2077 return ret;
2078}
2079
2080bool is_a2dp_device(snd_device_t out_snd_device)
2081{
2082 bool ret=false;
2083 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2084 ret = true;
2085
2086 return ret;
2087}
2088
2089bool is_bt_soc_on(struct audio_device *adev)
2090{
2091 struct mixer_ctl *ctl;
2092 char *mixer_ctl_name = "BT SOC status";
2093 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2094 bool bt_soc_status = true;
2095 if (!ctl) {
2096 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2097 __func__, mixer_ctl_name);
2098 /*This is to ensure we dont break targets which dont have the kernel change*/
2099 return true;
2100 }
2101 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2102 ALOGD("BT SOC status: %d",bt_soc_status);
2103 return bt_soc_status;
2104}
2105
2106int out_standby_l(struct audio_stream *stream);
2107
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002108int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002110 snd_device_t out_snd_device = SND_DEVICE_NONE;
2111 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002112 struct audio_usecase *usecase = NULL;
2113 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002114 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002115 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302116 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002117 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002118 int status = 0;
Jhansi Konathala902fc412018-09-05 13:21:44 +05302119 audio_devices_t audio_device = AUDIO_DEVICE_NONE;
2120 audio_channel_mask_t channel_mask = AUDIO_CHANNEL_NONE;
2121 int sample_rate = 0;
2122 int acdb_id = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302124 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2125
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002126 usecase = get_usecase_from_list(adev, uc_id);
2127 if (usecase == NULL) {
2128 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2129 return -EINVAL;
2130 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002132 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002133 (usecase->type == VOIP_CALL) ||
2134 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302135 if(usecase->stream.out == NULL) {
2136 ALOGE("%s: stream.out is NULL", __func__);
2137 return -EINVAL;
2138 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002139 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002140 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002141 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002142 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302143 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302144 if (usecase->stream.inout == NULL) {
2145 ALOGE("%s: stream.inout is NULL", __func__);
2146 return -EINVAL;
2147 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302148 stream_out.devices = usecase->stream.inout->out_config.devices;
2149 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2150 stream_out.format = usecase->stream.inout->out_config.format;
2151 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2152 out_snd_device = platform_get_output_snd_device(adev->platform,
2153 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302154 usecase->devices = out_snd_device;
2155 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2156 if (usecase->stream.inout == NULL) {
2157 ALOGE("%s: stream.inout is NULL", __func__);
2158 return -EINVAL;
2159 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302160 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302161 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002162 } else {
2163 /*
2164 * If the voice call is active, use the sound devices of voice call usecase
2165 * so that it would not result any device switch. All the usecases will
2166 * be switched to new device when select_devices() is called for voice call
2167 * usecase. This is to avoid switching devices for voice call when
2168 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002169 * choose voice call device only if the use case device is
2170 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002171 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002172 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002173 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002174 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002175 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2176 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302177 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2178 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002179 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002180 in_snd_device = vc_usecase->in_snd_device;
2181 out_snd_device = vc_usecase->out_snd_device;
2182 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002183 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002184 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002185 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002186 if ((voip_usecase != NULL) &&
2187 (usecase->type == PCM_PLAYBACK) &&
2188 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002189 out_snd_device_backend_match = platform_check_backends_match(
2190 voip_usecase->out_snd_device,
2191 platform_get_output_snd_device(
2192 adev->platform,
2193 usecase->stream.out));
2194 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002195 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002196 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2197 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002198 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002199 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002200 in_snd_device = voip_usecase->in_snd_device;
2201 out_snd_device = voip_usecase->out_snd_device;
2202 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002203 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002204 hfp_ucid = audio_extn_hfp_get_usecase();
2205 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002206 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002207 in_snd_device = hfp_usecase->in_snd_device;
2208 out_snd_device = hfp_usecase->out_snd_device;
2209 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002210 }
2211 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302212 if (usecase->stream.out == NULL) {
2213 ALOGE("%s: stream.out is NULL", __func__);
2214 return -EINVAL;
2215 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002216 usecase->devices = usecase->stream.out->devices;
2217 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002218 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002219 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002220 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002221 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizb27e7952018-10-12 15:49:35 +08002222 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002223 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2224
2225 if ((usecase->stream.out != NULL &&
2226 voip_usecase != NULL &&
2227 usecase->stream.out->usecase == voip_usecase->id) &&
2228 adev->active_input &&
Aalique Grahame22e49102018-12-18 14:23:57 -08002229 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2230 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
kunleizdcf967a2018-08-07 17:09:11 +08002231 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002232 select_devices(adev, adev->active_input->usecase);
2233 }
2234 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002235 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302236 if (usecase->stream.in == NULL) {
2237 ALOGE("%s: stream.in is NULL", __func__);
2238 return -EINVAL;
2239 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002240 usecase->devices = usecase->stream.in->device;
2241 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002242 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002243 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002244 if (adev->active_input &&
2245 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302246 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002247 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2248 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2249 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2250 out_device = voip_usecase->stream.out->devices;
2251 else if (adev->primary_output && !adev->primary_output->standby)
2252 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002253 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002254 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2255 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002256 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002257 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002258 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002259 }
2260 }
2261
2262 if (out_snd_device == usecase->out_snd_device &&
2263 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302264
2265 if (!force_device_switch(usecase))
2266 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002267 }
2268
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302269 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002270 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302271 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2272 return 0;
2273 }
2274
Aalique Grahame22e49102018-12-18 14:23:57 -08002275 if (out_snd_device != SND_DEVICE_NONE &&
2276 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2277 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2278 __func__,
2279 use_case_table[uc_id],
2280 adev->last_logged_snd_device[uc_id][0],
2281 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2282 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2283 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2284 -1,
2285 out_snd_device,
2286 platform_get_snd_device_name(out_snd_device),
2287 platform_get_snd_device_acdb_id(out_snd_device));
2288 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2289 }
2290 if (in_snd_device != SND_DEVICE_NONE &&
2291 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2292 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2293 __func__,
2294 use_case_table[uc_id],
2295 adev->last_logged_snd_device[uc_id][1],
2296 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2297 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2298 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2299 -1,
2300 in_snd_device,
2301 platform_get_snd_device_name(in_snd_device),
2302 platform_get_snd_device_acdb_id(in_snd_device));
2303 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2304 }
2305
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002306
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002307 /*
2308 * Limitation: While in call, to do a device switch we need to disable
2309 * and enable both RX and TX devices though one of them is same as current
2310 * device.
2311 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002312 if ((usecase->type == VOICE_CALL) &&
2313 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2314 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002315 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002316 }
2317
2318 if (((usecase->type == VOICE_CALL) ||
2319 (usecase->type == VOIP_CALL)) &&
2320 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2321 /* Disable sidetone only if voice/voip call already exists */
2322 if (voice_is_call_state_active(adev) ||
2323 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002324 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002325
2326 /* Disable aanc only if voice call exists */
2327 if (voice_is_call_state_active(adev))
2328 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002329 }
2330
Aalique Grahame22e49102018-12-18 14:23:57 -08002331 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2332 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002333 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302334 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002335 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2336 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2337 else
2338 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302339 }
2340
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002341 /* Disable current sound devices */
2342 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002343 disable_audio_route(adev, usecase);
2344 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002345 }
2346
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002347 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002348 disable_audio_route(adev, usecase);
2349 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350 }
2351
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002352 /* Applicable only on the targets that has external modem.
2353 * New device information should be sent to modem before enabling
2354 * the devices to reduce in-call device switch time.
2355 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002356 if ((usecase->type == VOICE_CALL) &&
2357 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2358 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002359 status = platform_switch_voice_call_enable_device_config(adev->platform,
2360 out_snd_device,
2361 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002362 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002363
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002364 /* Enable new sound devices */
2365 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002366 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302367 if (platform_check_codec_asrc_support(adev->platform))
2368 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002369 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002370 }
2371
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002372 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302373 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002374 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002375 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002376
Avinash Vaish71a8b972014-07-24 15:36:33 +05302377 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002378 status = platform_switch_voice_call_device_post(adev->platform,
2379 out_snd_device,
2380 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302381 enable_audio_route_for_voice_usecases(adev, usecase);
2382 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002383
sangwoo170731f2013-06-08 15:36:36 +09002384 usecase->in_snd_device = in_snd_device;
2385 usecase->out_snd_device = out_snd_device;
2386
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302387 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2388 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302389 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002390 if ((24 == usecase->stream.out->bit_width) &&
2391 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2392 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2393 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2394 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2395 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2396 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2397 /*
2398 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2399 * configured device sample rate, if not update the COPP rate to be equal to the
2400 * device sample rate, else open COPP at stream sample rate
2401 */
2402 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2403 usecase->stream.out->sample_rate,
2404 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302405 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2406 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002407 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2408 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2409 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2410 }
2411
Weiyin Jiang5d608082018-02-01 17:24:33 +08002412 /* Cache stream information to be notified to gef clients */
2413 audio_device = usecase->stream.out->devices;
2414 channel_mask = usecase->stream.out->channel_mask;
2415 sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
2416 acdb_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302417 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002418 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002419
Aalique Grahame22e49102018-12-18 14:23:57 -08002420 audio_extn_ma_set_device(usecase);
2421
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002422 /* If input stream is already running then effect needs to be
2423 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002424 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2425 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002426 check_and_enable_effect(adev);
2427
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002428 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002429 /* Enable aanc only if voice call exists */
2430 if (voice_is_call_state_active(adev))
2431 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2432
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002433 /* Enable sidetone only if other voice/voip call already exists */
2434 if (voice_is_call_state_active(adev) ||
2435 voice_extn_compress_voip_is_started(adev))
2436 voice_set_sidetone(adev, out_snd_device, true);
2437 }
2438
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002439 /* Applicable only on the targets that has external modem.
2440 * Enable device command should be sent to modem only after
2441 * enabling voice call mixer controls
2442 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002443 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002444 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2445 out_snd_device,
2446 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302447
2448 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2449
2450 if (usecase->type == VOIP_CALL) {
2451 if (adev->active_input != NULL &&
2452 !adev->active_input->standby) {
2453 if (is_bt_soc_on(adev) == false){
2454 ALOGD("BT SCO MIC disconnected while in connection");
2455 if (adev->active_input->pcm != NULL)
2456 pcm_stop(adev->active_input->pcm);
2457 }
2458 }
2459 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2460 && usecase->stream.out->started) {
2461 if (is_bt_soc_on(adev) == false) {
2462 ALOGD("BT SCO/A2DP disconnected while in connection");
2463 out_standby_l(&usecase->stream.out->stream.common);
2464 }
2465 }
2466 } else if ((usecase->stream.out != NULL) &&
2467 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302468 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2469 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302470 usecase->stream.out->started) {
2471 if (is_bt_soc_on(adev) == false) {
2472 ALOGD("BT SCO/A2dp disconnected while in connection");
2473 out_standby_l(&usecase->stream.out->stream.common);
2474 }
2475 }
2476 }
2477
Weiyin Jiang5d608082018-02-01 17:24:33 +08002478 /* Notify device change info to effect clients registered
2479 * NOTE: device lock has to be unlock temporarily here.
2480 * To the worst case, we notify stale info to clients.
2481 */
2482 if (usecase->type == PCM_PLAYBACK) {
2483 pthread_mutex_unlock(&adev->lock);
2484 audio_extn_gef_notify_device_config(audio_device, channel_mask, sample_rate, acdb_id);
2485 pthread_mutex_lock(&adev->lock);
2486 }
2487
Aalique Grahame22e49102018-12-18 14:23:57 -08002488 if (usecase == voip_usecase) {
2489 struct stream_out *voip_out = voip_usecase->stream.out;
2490 audio_extn_utils_send_app_type_gain(adev,
2491 voip_out->app_type_cfg.app_type,
2492 &voip_out->app_type_cfg.gain[0]);
2493 }
2494
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302495 ALOGD("%s: done",__func__);
2496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497 return status;
2498}
2499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500static int stop_input_stream(struct stream_in *in)
2501{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302502 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302504
2505 if (in == NULL) {
2506 ALOGE("%s: stream_in ptr is NULL", __func__);
2507 return -EINVAL;
2508 }
2509
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510 struct audio_device *adev = in->dev;
2511
Eric Laurent994a6932013-07-17 11:51:42 -07002512 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002513 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514 uc_info = get_usecase_from_list(adev, in->usecase);
2515 if (uc_info == NULL) {
2516 ALOGE("%s: Could not find the usecase (%d) in the list",
2517 __func__, in->usecase);
2518 return -EINVAL;
2519 }
2520
Derek Chend2530072014-11-24 12:39:14 -08002521 if (uc_info->in_snd_device != SND_DEVICE_NONE) {
2522 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2523 ALOGE("%s: failed to stop ext hw plugin", __func__);
2524 }
2525
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002526 /* Close in-call recording streams */
2527 voice_check_and_stop_incall_rec_usecase(adev, in);
2528
Eric Laurent150dbfe2013-02-27 14:31:02 -08002529 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002530 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002531
2532 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002533 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002535 list_remove(&uc_info->list);
2536 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002538 adev->active_input = get_next_active_input(adev);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302539 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002540 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541 return ret;
2542}
2543
2544int start_input_stream(struct stream_in *in)
2545{
2546 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002547 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302549
2550 if (in == NULL) {
2551 ALOGE("%s: stream_in ptr is NULL", __func__);
2552 return -EINVAL;
2553 }
2554
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002556 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002557 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558
Mingming Yin2664a5b2015-09-03 10:53:11 -07002559 if (get_usecase_from_list(adev, usecase) == NULL)
2560 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302561 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2562 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002563
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302564 if (CARD_STATUS_OFFLINE == in->card_status||
2565 CARD_STATUS_OFFLINE == adev->card_status) {
2566 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302567 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302568 goto error_config;
2569 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302570
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302571 if (audio_is_bluetooth_sco_device(in->device)) {
2572 if (!adev->bt_sco_on) {
2573 ALOGE("%s: SCO profile is not ready, return error", __func__);
2574 ret = -EIO;
2575 goto error_config;
2576 }
2577 }
2578
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002579 /* Check if source matches incall recording usecase criteria */
2580 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2581 if (ret)
2582 goto error_config;
2583 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002584 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2585
2586 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2587 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2588 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002589 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002590 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002591
Eric Laurentb23d5282013-05-14 15:27:20 -07002592 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593 if (in->pcm_device_id < 0) {
2594 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2595 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002596 ret = -EINVAL;
2597 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002599
2600 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002602
2603 if (!uc_info) {
2604 ret = -ENOMEM;
2605 goto error_config;
2606 }
2607
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608 uc_info->id = in->usecase;
2609 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002610 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002611 uc_info->devices = in->device;
2612 uc_info->in_snd_device = SND_DEVICE_NONE;
2613 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002615 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302616 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2617 adev->perf_lock_opts,
2618 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002619 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002620
Derek Chend2530072014-11-24 12:39:14 -08002621 if (uc_info->in_snd_device != SND_DEVICE_NONE) {
2622 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2623 ALOGE("%s: failed to start ext hw plugin", __func__);
2624 }
2625
Haynes Mathew George16081042017-05-31 17:16:49 -07002626 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302627 ret = audio_extn_cin_start_input_stream(in);
2628 if (ret)
2629 goto error_open;
2630 else
2631 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002632 }
2633
Haynes Mathew George16081042017-05-31 17:16:49 -07002634 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002635 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002636 ALOGE("%s: pcm stream not ready", __func__);
2637 goto error_open;
2638 }
2639 ret = pcm_start(in->pcm);
2640 if (ret < 0) {
2641 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2642 goto error_open;
2643 }
2644 } else {
2645 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2646 unsigned int pcm_open_retry_count = 0;
2647
2648 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2649 flags |= PCM_MMAP | PCM_NOIRQ;
2650 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2651 } else if (in->realtime) {
2652 flags |= PCM_MMAP | PCM_NOIRQ;
2653 }
2654
Garmond Leunge2433c32017-09-28 21:51:22 -07002655 if (audio_extn_ffv_get_stream() == in) {
2656 ALOGD("%s: ffv stream, update pcm config", __func__);
2657 audio_extn_ffv_update_pcm_config(&config);
2658 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002659 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2660 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2661
2662 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002663 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002664 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002665 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002666 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302667 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302668 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2669 adev->card_status = CARD_STATUS_OFFLINE;
2670 in->card_status = CARD_STATUS_OFFLINE;
2671 ret = -EIO;
2672 goto error_open;
2673 }
2674
Haynes Mathew George16081042017-05-31 17:16:49 -07002675 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2676 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2677 if (in->pcm != NULL) {
2678 pcm_close(in->pcm);
2679 in->pcm = NULL;
2680 }
2681 if (pcm_open_retry_count-- == 0) {
2682 ret = -EIO;
2683 goto error_open;
2684 }
2685 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2686 continue;
2687 }
2688 break;
2689 }
2690
2691 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002692 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002693 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002694 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002695 if (ret < 0) {
2696 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2697 pcm_close(in->pcm);
2698 in->pcm = NULL;
2699 goto error_open;
2700 }
2701 register_in_stream(in);
2702 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002703 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002704 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002705 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002706 if (ret < 0) {
2707 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002708 pcm_close(in->pcm);
2709 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002710 goto error_open;
2711 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002712 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002713 }
2714
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002715 check_and_enable_effect(adev);
2716
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302717done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302718 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002719 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302720 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002721 return ret;
2722
2723error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302724 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002726error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302727 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302728 /*
2729 * sleep 50ms to allow sufficient time for kernel
2730 * drivers to recover incases like SSR.
2731 */
2732 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002733 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302734 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002735 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736}
2737
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002738void lock_input_stream(struct stream_in *in)
2739{
2740 pthread_mutex_lock(&in->pre_lock);
2741 pthread_mutex_lock(&in->lock);
2742 pthread_mutex_unlock(&in->pre_lock);
2743}
2744
2745void lock_output_stream(struct stream_out *out)
2746{
2747 pthread_mutex_lock(&out->pre_lock);
2748 pthread_mutex_lock(&out->lock);
2749 pthread_mutex_unlock(&out->pre_lock);
2750}
2751
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002752/* must be called with out->lock locked */
2753static int send_offload_cmd_l(struct stream_out* out, int command)
2754{
2755 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2756
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002757 if (!cmd) {
2758 ALOGE("failed to allocate mem for command 0x%x", command);
2759 return -ENOMEM;
2760 }
2761
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002762 ALOGVV("%s %d", __func__, command);
2763
2764 cmd->cmd = command;
2765 list_add_tail(&out->offload_cmd_list, &cmd->node);
2766 pthread_cond_signal(&out->offload_cond);
2767 return 0;
2768}
2769
2770/* must be called iwth out->lock locked */
2771static void stop_compressed_output_l(struct stream_out *out)
2772{
2773 out->offload_state = OFFLOAD_STATE_IDLE;
2774 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002775 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002776 if (out->compr != NULL) {
2777 compress_stop(out->compr);
2778 while (out->offload_thread_blocked) {
2779 pthread_cond_wait(&out->cond, &out->lock);
2780 }
2781 }
2782}
2783
Varun Balaraje49253e2017-07-06 19:48:56 +05302784bool is_interactive_usecase(audio_usecase_t uc_id)
2785{
2786 unsigned int i;
2787 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2788 if (uc_id == interactive_usecases[i])
2789 return true;
2790 }
2791 return false;
2792}
2793
2794static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2795{
2796 audio_usecase_t ret_uc = USECASE_INVALID;
2797 unsigned int intract_uc_index;
2798 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2799
2800 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2801 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2802 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2803 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2804 ret_uc = interactive_usecases[intract_uc_index];
2805 break;
2806 }
2807 }
2808
2809 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2810 return ret_uc;
2811}
2812
2813static void free_interactive_usecase(struct audio_device *adev,
2814 audio_usecase_t uc_id)
2815{
2816 unsigned int interact_uc_index;
2817 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2818
2819 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2820 if (interactive_usecases[interact_uc_index] == uc_id) {
2821 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2822 break;
2823 }
2824 }
2825 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2826}
2827
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002828bool is_offload_usecase(audio_usecase_t uc_id)
2829{
2830 unsigned int i;
2831 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2832 if (uc_id == offload_usecases[i])
2833 return true;
2834 }
2835 return false;
2836}
2837
Dhananjay Kumarac341582017-02-23 23:42:25 +05302838static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002839{
vivek mehta446c3962015-09-14 10:57:35 -07002840 audio_usecase_t ret_uc = USECASE_INVALID;
2841 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002842 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002843 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302844 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002845 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2846 else
2847 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002848
vivek mehta446c3962015-09-14 10:57:35 -07002849 pthread_mutex_lock(&adev->lock);
2850 if (get_usecase_from_list(adev, ret_uc) != NULL)
2851 ret_uc = USECASE_INVALID;
2852 pthread_mutex_unlock(&adev->lock);
2853
2854 return ret_uc;
2855 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002856
2857 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002858 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2859 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2860 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2861 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002862 break;
2863 }
2864 }
vivek mehta446c3962015-09-14 10:57:35 -07002865
2866 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2867 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002868}
2869
2870static void free_offload_usecase(struct audio_device *adev,
2871 audio_usecase_t uc_id)
2872{
vivek mehta446c3962015-09-14 10:57:35 -07002873 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002874 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002875
2876 if (!adev->multi_offload_enable)
2877 return;
2878
2879 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2880 if (offload_usecases[offload_uc_index] == uc_id) {
2881 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002882 break;
2883 }
2884 }
2885 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2886}
2887
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002888static void *offload_thread_loop(void *context)
2889{
2890 struct stream_out *out = (struct stream_out *) context;
2891 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002892 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002893
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002894 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2895 set_sched_policy(0, SP_FOREGROUND);
2896 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2897
2898 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002899 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 for (;;) {
2901 struct offload_cmd *cmd = NULL;
2902 stream_callback_event_t event;
2903 bool send_callback = false;
2904
2905 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2906 __func__, list_empty(&out->offload_cmd_list),
2907 out->offload_state);
2908 if (list_empty(&out->offload_cmd_list)) {
2909 ALOGV("%s SLEEPING", __func__);
2910 pthread_cond_wait(&out->offload_cond, &out->lock);
2911 ALOGV("%s RUNNING", __func__);
2912 continue;
2913 }
2914
2915 item = list_head(&out->offload_cmd_list);
2916 cmd = node_to_item(item, struct offload_cmd, node);
2917 list_remove(item);
2918
2919 ALOGVV("%s STATE %d CMD %d out->compr %p",
2920 __func__, out->offload_state, cmd->cmd, out->compr);
2921
2922 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2923 free(cmd);
2924 break;
2925 }
2926
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002927 // allow OFFLOAD_CMD_ERROR reporting during standby
2928 // this is needed to handle failures during compress_open
2929 // Note however that on a pause timeout, the stream is closed
2930 // and no offload usecase will be active. Therefore this
2931 // special case is needed for compress_open failures alone
2932 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2933 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002934 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002935 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002936 pthread_cond_signal(&out->cond);
2937 continue;
2938 }
2939 out->offload_thread_blocked = true;
2940 pthread_mutex_unlock(&out->lock);
2941 send_callback = false;
2942 switch(cmd->cmd) {
2943 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002944 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002945 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002946 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002947 send_callback = true;
2948 event = STREAM_CBK_EVENT_WRITE_READY;
2949 break;
2950 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002951 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302952 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002953 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302954 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002955 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302956 if (ret < 0)
2957 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302958 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302959 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002960 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002961 else
2962 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002963 if (-ENETRESET != ret && !(-EINTR == ret &&
2964 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302965 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302966 pthread_mutex_lock(&out->lock);
2967 out->send_new_metadata = 1;
2968 out->send_next_track_params = true;
2969 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302970 event = STREAM_CBK_EVENT_DRAIN_READY;
2971 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2972 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302973 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002974 break;
2975 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002976 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002977 ret = compress_drain(out->compr);
2978 ALOGD("copl(%p):out of compress_drain", out);
2979 // EINTR check avoids drain interruption due to SSR
2980 if (-ENETRESET != ret && !(-EINTR == ret &&
2981 CARD_STATUS_OFFLINE == out->card_status)) {
2982 send_callback = true;
2983 event = STREAM_CBK_EVENT_DRAIN_READY;
2984 } else
2985 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002986 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302987 case OFFLOAD_CMD_ERROR:
2988 ALOGD("copl(%p): sending error callback to AF", out);
2989 send_callback = true;
2990 event = STREAM_CBK_EVENT_ERROR;
2991 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002992 default:
2993 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2994 break;
2995 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002996 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002997 out->offload_thread_blocked = false;
2998 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002999 if (send_callback && out->client_callback) {
3000 ALOGVV("%s: sending client_callback event %d", __func__, event);
3001 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003002 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003003 free(cmd);
3004 }
3005
3006 pthread_cond_signal(&out->cond);
3007 while (!list_empty(&out->offload_cmd_list)) {
3008 item = list_head(&out->offload_cmd_list);
3009 list_remove(item);
3010 free(node_to_item(item, struct offload_cmd, node));
3011 }
3012 pthread_mutex_unlock(&out->lock);
3013
3014 return NULL;
3015}
3016
3017static int create_offload_callback_thread(struct stream_out *out)
3018{
3019 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3020 list_init(&out->offload_cmd_list);
3021 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3022 offload_thread_loop, out);
3023 return 0;
3024}
3025
3026static int destroy_offload_callback_thread(struct stream_out *out)
3027{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003028 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003029 stop_compressed_output_l(out);
3030 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3031
3032 pthread_mutex_unlock(&out->lock);
3033 pthread_join(out->offload_thread, (void **) NULL);
3034 pthread_cond_destroy(&out->offload_cond);
3035
3036 return 0;
3037}
3038
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003039static int stop_output_stream(struct stream_out *out)
3040{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303041 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042 struct audio_usecase *uc_info;
3043 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003044 bool has_voip_usecase =
3045 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003046
Eric Laurent994a6932013-07-17 11:51:42 -07003047 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003048 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049 uc_info = get_usecase_from_list(adev, out->usecase);
3050 if (uc_info == NULL) {
3051 ALOGE("%s: Could not find the usecase (%d) in the list",
3052 __func__, out->usecase);
3053 return -EINVAL;
3054 }
3055
Derek Chend2530072014-11-24 12:39:14 -08003056 if (uc_info->out_snd_device != SND_DEVICE_NONE) {
3057 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3058 ALOGE("%s: failed to stop ext hw plugin", __func__);
3059 }
3060
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003061 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303062 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003063 if (adev->visualizer_stop_output != NULL)
3064 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003065
3066 audio_extn_dts_remove_state_notifier_node(out->usecase);
3067
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003068 if (adev->offload_effects_stop_output != NULL)
3069 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
3070 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003071
Arun Mirpurief53ce52018-09-11 18:00:09 -07003072 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3073 voice_set_device_mute_flag(adev, false);
3074
Eric Laurent150dbfe2013-02-27 14:31:02 -08003075 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003076 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003077
3078 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003079 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080
Aalique Grahame22e49102018-12-18 14:23:57 -08003081 audio_extn_extspk_update(adev->extspk);
3082
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003083 if (is_offload_usecase(out->usecase)) {
3084 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3085 adev->dsp_bit_width_enforce_mode,
3086 false);
3087 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003088 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3089 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3090 false);
3091
3092 if (ret != 0)
3093 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3094 /* default service interval was successfully updated,
3095 reopen USB backend with new service interval */
3096 ret = 0;
3097 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003098
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003099 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303100 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003101 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303102 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003103 ALOGV("Disable passthrough , reset mixer to pcm");
3104 /* NO_PASSTHROUGH */
3105 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003106 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003107 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3108 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003109
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303110 /* Must be called after removing the usecase from list */
3111 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303112 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303113
Manish Dewangan21a850a2017-08-14 12:03:55 +05303114 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003115 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3116 if (ret < 0)
3117 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3118 }
3119
Aalique Grahame22e49102018-12-18 14:23:57 -08003120 if (has_voip_usecase ||
3121 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3122 struct listnode *node;
3123 struct audio_usecase *usecase;
3124 list_for_each(node, &adev->usecase_list) {
3125 usecase = node_to_item(node, struct audio_usecase, list);
3126 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
3127 continue;
3128
3129 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3130 __func__, usecase->id, use_case_table[usecase->id],
3131 out->usecase, use_case_table[out->usecase]);
3132 select_devices(adev, usecase->id);
3133 }
3134 }
3135
Garmond Leung5fd0b552018-04-17 11:56:12 -07003136 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003137 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138 return ret;
3139}
3140
3141int start_output_stream(struct stream_out *out)
3142{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 struct audio_usecase *uc_info;
3145 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003146 char mixer_ctl_name[128];
3147 struct mixer_ctl *ctl = NULL;
3148 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303149 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150
Haynes Mathew George380745d2017-10-04 15:27:45 -07003151 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003152 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3153 ret = -EINVAL;
3154 goto error_config;
3155 }
3156
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303157 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
3158 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
3159 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303160
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303161 if (CARD_STATUS_OFFLINE == out->card_status ||
3162 CARD_STATUS_OFFLINE == adev->card_status) {
3163 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303164 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303165 goto error_config;
3166 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303167
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303168 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003169 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003170 if (out->devices &
3171 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303172 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303173 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303174 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3175 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3176 ret = -EAGAIN;
3177 goto error_config;
3178 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303179 }
3180 }
3181 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303182 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3183 if (!adev->bt_sco_on) {
3184 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3185 //combo usecase just by pass a2dp
3186 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3187 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3188 } else {
3189 ALOGE("%s: SCO profile is not ready, return error", __func__);
3190 ret = -EAGAIN;
3191 goto error_config;
3192 }
3193 }
3194 }
3195
Eric Laurentb23d5282013-05-14 15:27:20 -07003196 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197 if (out->pcm_device_id < 0) {
3198 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3199 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003200 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003201 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003202 }
3203
3204 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003205
3206 if (!uc_info) {
3207 ret = -ENOMEM;
3208 goto error_config;
3209 }
3210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211 uc_info->id = out->usecase;
3212 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003213 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003214 uc_info->devices = out->devices;
3215 uc_info->in_snd_device = SND_DEVICE_NONE;
3216 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003217
3218 /* This must be called before adding this usecase to the list */
3219 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3220 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3221 /* USB backend is not reopened immediately.
3222 This is eventually done as part of select_devices */
3223 }
3224
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003225 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303227 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3228 adev->perf_lock_opts,
3229 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303230
3231 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303232 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303233 if (audio_extn_passthru_is_enabled() &&
3234 audio_extn_passthru_is_passthrough_stream(out)) {
3235 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303236 }
3237 }
3238
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303239 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003240 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303241 if (!a2dp_combo) {
3242 check_a2dp_restore_l(adev, out, false);
3243 } else {
3244 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003245 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3246 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3247 else
3248 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303249 select_devices(adev, out->usecase);
3250 out->devices = dev;
3251 }
3252 } else {
3253 select_devices(adev, out->usecase);
3254 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003255
Arun Mirpurief53ce52018-09-11 18:00:09 -07003256 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3257 voice_set_device_mute_flag(adev, true);
3258
Derek Chend2530072014-11-24 12:39:14 -08003259 if (uc_info->out_snd_device != SND_DEVICE_NONE) {
3260 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3261 ALOGE("%s: failed to start ext hw plugin", __func__);
3262 }
3263
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003264 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3265 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003266
3267 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3268 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3269 ALOGE("%s: pcm stream not ready", __func__);
3270 goto error_open;
3271 }
3272 ret = pcm_start(out->pcm);
3273 if (ret < 0) {
3274 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3275 goto error_open;
3276 }
3277 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003278 unsigned int flags = PCM_OUT;
3279 unsigned int pcm_open_retry_count = 0;
3280 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3281 flags |= PCM_MMAP | PCM_NOIRQ;
3282 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003283 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003284 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003285 } else
3286 flags |= PCM_MONOTONIC;
3287
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003288 if ((adev->vr_audio_mode_enabled) &&
3289 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3290 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3291 "PCM_Dev %d Topology", out->pcm_device_id);
3292 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3293 if (!ctl) {
3294 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3295 __func__, mixer_ctl_name);
3296 } else {
3297 //if success use ULLPP
3298 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3299 __func__, mixer_ctl_name, out->pcm_device_id);
3300 //There is a still a possibility that some sessions
3301 // that request for FAST|RAW when 3D audio is active
3302 //can go through ULLPP. Ideally we expects apps to
3303 //listen to audio focus and stop concurrent playback
3304 //Also, we will look for mode flag (voice_in_communication)
3305 //before enabling the realtime flag.
3306 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3307 }
3308 }
3309
Surendar Karka91fa3682018-07-02 18:12:12 +05303310 if (out->realtime)
3311 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3312 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3313
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003314 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003315 ATRACE_BEGIN("pcm_open");
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003316 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3317 flags, &out->config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003318 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303319 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303320 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3321 out->card_status = CARD_STATUS_OFFLINE;
3322 adev->card_status = CARD_STATUS_OFFLINE;
3323 ret = -EIO;
3324 goto error_open;
3325 }
3326
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003327 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3328 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3329 if (out->pcm != NULL) {
3330 pcm_close(out->pcm);
3331 out->pcm = NULL;
3332 }
3333 if (pcm_open_retry_count-- == 0) {
3334 ret = -EIO;
3335 goto error_open;
3336 }
3337 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3338 continue;
3339 }
3340 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003341 }
Surendar Karka91fa3682018-07-02 18:12:12 +05303342 if (!out->realtime)
3343 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303344 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003345
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003346 ALOGV("%s: pcm_prepare", __func__);
3347 if (pcm_is_ready(out->pcm)) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003348 ATRACE_BEGIN("pcm_prepare");
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003349 ret = pcm_prepare(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003350 ATRACE_END();
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003351 if (ret < 0) {
3352 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3353 pcm_close(out->pcm);
3354 out->pcm = NULL;
3355 goto error_open;
3356 }
3357 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08003358 // apply volume for voip playback after path is set up
3359 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3360 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303361 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3362 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303363 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3364 out->apply_volume = false;
3365 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003366 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003367 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303368 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003369 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3370 adev->dsp_bit_width_enforce_mode,
3371 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003373 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003374 out->compr = compress_open(adev->snd_card,
3375 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003376 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003377 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303378 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303379 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3380 adev->card_status = CARD_STATUS_OFFLINE;
3381 out->card_status = CARD_STATUS_OFFLINE;
3382 ret = -EIO;
3383 goto error_open;
3384 }
3385
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003386 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003387 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003388 compress_close(out->compr);
3389 out->compr = NULL;
3390 ret = -EIO;
3391 goto error_open;
3392 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303393 /* compress_open sends params of the track, so reset the flag here */
3394 out->is_compr_metadata_avail = false;
3395
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003396 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003397 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003398
Fred Oh3f43e742015-03-04 18:42:34 -08003399 /* Since small bufs uses blocking writes, a write will be blocked
3400 for the default max poll time (20s) in the event of an SSR.
3401 Reduce the poll time to observe and deal with SSR faster.
3402 */
Ashish Jain5106d362016-05-11 19:23:33 +05303403 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003404 compress_set_max_poll_wait(out->compr, 1000);
3405 }
3406
Manish Dewangan69426c82017-01-30 17:35:36 +05303407 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303408 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303409
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003410 audio_extn_dts_create_state_notifier_node(out->usecase);
3411 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3412 popcount(out->channel_mask),
3413 out->playback_started);
3414
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003415#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303416 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003417 audio_extn_dolby_send_ddp_endp_params(adev);
3418#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303419 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3420 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003421 if (adev->visualizer_start_output != NULL)
3422 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3423 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303424 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003425 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003426 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003428
3429 if (ret == 0) {
3430 register_out_stream(out);
3431 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003432 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3433 ALOGE("%s: pcm stream not ready", __func__);
3434 goto error_open;
3435 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003436 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003437 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003438 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003439 if (ret < 0)
3440 goto error_open;
3441 }
3442 }
3443
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303444 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003445 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003446
Manish Dewangan21a850a2017-08-14 12:03:55 +05303447 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003448 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003449 if (ret < 0)
3450 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3451 }
3452
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003453 // consider a scenario where on pause lower layers are tear down.
3454 // so on resume, swap mixer control need to be sent only when
3455 // backend is active, hence rather than sending from enable device
3456 // sending it from start of streamtream
3457
3458 platform_set_swap_channels(adev, true);
3459
Haynes Mathew George380745d2017-10-04 15:27:45 -07003460 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303461 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003462 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003463error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303464 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003466error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303467 /*
3468 * sleep 50ms to allow sufficient time for kernel
3469 * drivers to recover incases like SSR.
3470 */
3471 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003472 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303473 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003474 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475}
3476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477static int check_input_parameters(uint32_t sample_rate,
3478 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003479 int channel_count,
3480 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003481{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003482 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303484 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3485 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3486 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003487 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003488 !audio_extn_compr_cap_format_supported(format) &&
3489 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003490 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003491
Aalique Grahame22e49102018-12-18 14:23:57 -08003492 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3493 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3494 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3495 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3496 return -EINVAL;
3497 }
3498
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003499 switch (channel_count) {
3500 case 1:
3501 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303502 case 3:
3503 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003504 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003505 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003506 break;
3507 default:
3508 ret = -EINVAL;
3509 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510
3511 switch (sample_rate) {
3512 case 8000:
3513 case 11025:
3514 case 12000:
3515 case 16000:
3516 case 22050:
3517 case 24000:
3518 case 32000:
3519 case 44100:
3520 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003521 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303522 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003523 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303524 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525 break;
3526 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003527 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528 }
3529
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003530 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531}
3532
Naresh Tanniru04f71882018-06-26 17:46:22 +05303533
3534/** Add a value in a list if not already present.
3535 * @return true if value was successfully inserted or already present,
3536 * false if the list is full and does not contain the value.
3537 */
3538static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3539 for (size_t i = 0; i < list_length; i++) {
3540 if (list[i] == value) return true; // value is already present
3541 if (list[i] == 0) { // no values in this slot
3542 list[i] = value;
3543 return true; // value inserted
3544 }
3545 }
3546 return false; // could not insert value
3547}
3548
3549/** Add channel_mask in supported_channel_masks if not already present.
3550 * @return true if channel_mask was successfully inserted or already present,
3551 * false if supported_channel_masks is full and does not contain channel_mask.
3552 */
3553static void register_channel_mask(audio_channel_mask_t channel_mask,
3554 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3555 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3556 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3557}
3558
3559/** Add format in supported_formats if not already present.
3560 * @return true if format was successfully inserted or already present,
3561 * false if supported_formats is full and does not contain format.
3562 */
3563static void register_format(audio_format_t format,
3564 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3565 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3566 "%s: stream can not declare supporting its format %x", __func__, format);
3567}
3568/** Add sample_rate in supported_sample_rates if not already present.
3569 * @return true if sample_rate was successfully inserted or already present,
3570 * false if supported_sample_rates is full and does not contain sample_rate.
3571 */
3572static void register_sample_rate(uint32_t sample_rate,
3573 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3574 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3575 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3576}
3577
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003578static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3579{
3580 uint32_t high = num1, low = num2, temp = 0;
3581
3582 if (!num1 || !num2)
3583 return 0;
3584
3585 if (num1 < num2) {
3586 high = num2;
3587 low = num1;
3588 }
3589
3590 while (low != 0) {
3591 temp = low;
3592 low = high % low;
3593 high = temp;
3594 }
3595 return (num1 * num2)/high;
3596}
3597
3598static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3599{
3600 uint32_t remainder = 0;
3601
3602 if (!multiplier)
3603 return num;
3604
3605 remainder = num % multiplier;
3606 if (remainder)
3607 num += (multiplier - remainder);
3608
3609 return num;
3610}
3611
Aalique Grahame22e49102018-12-18 14:23:57 -08003612static size_t get_stream_buffer_size(size_t duration_ms,
3613 uint32_t sample_rate,
3614 audio_format_t format,
3615 int channel_count,
3616 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617{
3618 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003619 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620
Aalique Grahame22e49102018-12-18 14:23:57 -08003621 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003622 if (is_low_latency)
3623 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303624
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003625 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08003626 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627
Ralf Herzbd08d632018-09-28 15:50:49 +02003628 /* make sure the size is multiple of 32 bytes and additionally multiple of
3629 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003630 * At 48 kHz mono 16-bit PCM:
3631 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3632 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003633 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003634 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003635 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003636
3637 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003638}
3639
Aalique Grahame22e49102018-12-18 14:23:57 -08003640static size_t get_input_buffer_size(uint32_t sample_rate,
3641 audio_format_t format,
3642 int channel_count,
3643 bool is_low_latency)
3644{
3645 /* Don't know if USB HIFI in this context so use true to be conservative */
3646 if (check_input_parameters(sample_rate, format, channel_count,
3647 true /*is_usb_hifi */) != 0)
3648 return 0;
3649
3650 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
3651 sample_rate,
3652 format,
3653 channel_count,
3654 is_low_latency);
3655}
3656
Ashish Jain058165c2016-09-28 23:18:48 +05303657static size_t get_output_period_size(uint32_t sample_rate,
3658 audio_format_t format,
3659 int channel_count,
3660 int duration /*in millisecs*/)
3661{
3662 size_t size = 0;
3663 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3664
3665 if ((duration == 0) || (sample_rate == 0) ||
3666 (bytes_per_sample == 0) || (channel_count == 0)) {
3667 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3668 bytes_per_sample, channel_count);
3669 return -EINVAL;
3670 }
3671
3672 size = (sample_rate *
3673 duration *
3674 bytes_per_sample *
3675 channel_count) / 1000;
3676 /*
3677 * To have same PCM samples for all channels, the buffer size requires to
3678 * be multiple of (number of channels * bytes per sample)
3679 * For writes to succeed, the buffer must be written at address which is multiple of 32
3680 */
3681 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3682
3683 return (size/(channel_count * bytes_per_sample));
3684}
3685
Zhou Song48453a02018-01-10 17:50:59 +08003686static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303687{
3688 uint64_t actual_frames_rendered = 0;
3689 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3690
3691 /* This adjustment accounts for buffering after app processor.
3692 * It is based on estimated DSP latency per use case, rather than exact.
3693 */
3694 int64_t platform_latency = platform_render_latency(out->usecase) *
3695 out->sample_rate / 1000000LL;
3696
Zhou Song48453a02018-01-10 17:50:59 +08003697 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303698 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3699 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3700 * hence only estimate.
3701 */
3702 int64_t signed_frames = out->written - kernel_buffer_size;
3703
3704 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3705
Zhou Song48453a02018-01-10 17:50:59 +08003706 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303707 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003708 if (timestamp != NULL )
3709 *timestamp = out->writeAt;
3710 } else if (timestamp != NULL) {
3711 clock_gettime(CLOCK_MONOTONIC, timestamp);
3712 }
3713 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303714
3715 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3716 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3717 (long long int)out->written, (int)kernel_buffer_size,
3718 audio_bytes_per_sample(out->compr_config.codec->format),
3719 popcount(out->channel_mask));
3720
3721 return actual_frames_rendered;
3722}
3723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3725{
3726 struct stream_out *out = (struct stream_out *)stream;
3727
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003728 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729}
3730
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003731static int out_set_sample_rate(struct audio_stream *stream __unused,
3732 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733{
3734 return -ENOSYS;
3735}
3736
3737static size_t out_get_buffer_size(const struct audio_stream *stream)
3738{
3739 struct stream_out *out = (struct stream_out *)stream;
3740
Varun Balaraje49253e2017-07-06 19:48:56 +05303741 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303742 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303743 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303744 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3745 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3746 else
3747 return out->compr_config.fragment_size;
3748 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003749 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003750 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3751 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 +05303752 else if (is_offload_usecase(out->usecase) &&
3753 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303754 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003755
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003756 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003757 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003758}
3759
3760static uint32_t out_get_channels(const struct audio_stream *stream)
3761{
3762 struct stream_out *out = (struct stream_out *)stream;
3763
3764 return out->channel_mask;
3765}
3766
3767static audio_format_t out_get_format(const struct audio_stream *stream)
3768{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003769 struct stream_out *out = (struct stream_out *)stream;
3770
3771 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772}
3773
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003774static int out_set_format(struct audio_stream *stream __unused,
3775 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776{
3777 return -ENOSYS;
3778}
3779
3780static int out_standby(struct audio_stream *stream)
3781{
3782 struct stream_out *out = (struct stream_out *)stream;
3783 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003784 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003785
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303786 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3787 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003789 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003790 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003791 if (adev->adm_deregister_stream)
3792 adev->adm_deregister_stream(adev->adm_data, out->handle);
3793
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003794 if (is_offload_usecase(out->usecase))
3795 stop_compressed_output_l(out);
3796
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003797 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003798 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003799 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3800 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303801 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003802 pthread_mutex_unlock(&adev->lock);
3803 pthread_mutex_unlock(&out->lock);
3804 ALOGD("VOIP output entered standby");
3805 return 0;
3806 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003807 if (out->pcm) {
3808 pcm_close(out->pcm);
3809 out->pcm = NULL;
3810 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003811 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3812 do_stop = out->playback_started;
3813 out->playback_started = false;
3814 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003815 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003816 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303817 out->send_next_track_params = false;
3818 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003819 out->gapless_mdata.encoder_delay = 0;
3820 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003821 if (out->compr != NULL) {
3822 compress_close(out->compr);
3823 out->compr = NULL;
3824 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003825 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003826 if (do_stop) {
3827 stop_output_stream(out);
3828 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003829 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003830 }
3831 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303832 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003833 return 0;
3834}
3835
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303836static int out_on_error(struct audio_stream *stream)
3837{
3838 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003839 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303840
3841 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003842 // always send CMD_ERROR for offload streams, this
3843 // is needed e.g. when SSR happens within compress_open
3844 // since the stream is active, offload_callback_thread is also active.
3845 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3846 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003847 }
3848 pthread_mutex_unlock(&out->lock);
3849
3850 status = out_standby(&out->stream.common);
3851
3852 lock_output_stream(out);
3853 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003854 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303855 }
3856 pthread_mutex_unlock(&out->lock);
3857
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003858 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303859}
3860
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303861/*
3862 *standby implementation without locks, assumes that the callee already
3863 *has taken adev and out lock.
3864 */
3865int out_standby_l(struct audio_stream *stream)
3866{
3867 struct stream_out *out = (struct stream_out *)stream;
3868 struct audio_device *adev = out->dev;
3869
3870 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3871 stream, out->usecase, use_case_table[out->usecase]);
3872
3873 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003874 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303875 if (adev->adm_deregister_stream)
3876 adev->adm_deregister_stream(adev->adm_data, out->handle);
3877
3878 if (is_offload_usecase(out->usecase))
3879 stop_compressed_output_l(out);
3880
3881 out->standby = true;
3882 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3883 voice_extn_compress_voip_close_output_stream(stream);
3884 out->started = 0;
3885 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003886 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303887 return 0;
3888 } else if (!is_offload_usecase(out->usecase)) {
3889 if (out->pcm) {
3890 pcm_close(out->pcm);
3891 out->pcm = NULL;
3892 }
3893 } else {
3894 ALOGD("copl(%p):standby", out);
3895 out->send_next_track_params = false;
3896 out->is_compr_metadata_avail = false;
3897 out->gapless_mdata.encoder_delay = 0;
3898 out->gapless_mdata.encoder_padding = 0;
3899 if (out->compr != NULL) {
3900 compress_close(out->compr);
3901 out->compr = NULL;
3902 }
3903 }
3904 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003905 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303906 }
3907 ALOGD("%s: exit", __func__);
3908 return 0;
3909}
3910
Aalique Grahame22e49102018-12-18 14:23:57 -08003911static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912{
Aalique Grahame22e49102018-12-18 14:23:57 -08003913 struct stream_out *out = (struct stream_out *)stream;
3914
3915 // We try to get the lock for consistency,
3916 // but it isn't necessary for these variables.
3917 // If we're not in standby, we may be blocked on a write.
3918 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
3919 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
3920 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
3921
3922 if (locked) {
3923 pthread_mutex_unlock(&out->lock);
3924 }
3925
3926 // dump error info
3927 (void)error_log_dump(
3928 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
3929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930 return 0;
3931}
3932
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003933static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3934{
3935 int ret = 0;
3936 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003937
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003938 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003939 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003940 return -EINVAL;
3941 }
3942
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303943 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003944
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003945 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3946 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303947 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003948 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003949 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3950 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303951 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003952 }
3953
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003954 ALOGV("%s new encoder delay %u and padding %u", __func__,
3955 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3956
3957 return 0;
3958}
3959
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003960static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3961{
3962 return out == adev->primary_output || out == adev->voice_tx_output;
3963}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003964
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303965// note: this call is safe only if the stream_cb is
3966// removed first in close_output_stream (as is done now).
3967static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3968{
3969 if (!stream || !parms)
3970 return;
3971
3972 struct stream_out *out = (struct stream_out *)stream;
3973 struct audio_device *adev = out->dev;
3974
3975 card_status_t status;
3976 int card;
3977 if (parse_snd_card_status(parms, &card, &status) < 0)
3978 return;
3979
3980 pthread_mutex_lock(&adev->lock);
3981 bool valid_cb = (card == adev->snd_card);
3982 pthread_mutex_unlock(&adev->lock);
3983
3984 if (!valid_cb)
3985 return;
3986
3987 lock_output_stream(out);
3988 if (out->card_status != status)
3989 out->card_status = status;
3990 pthread_mutex_unlock(&out->lock);
3991
3992 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3993 use_case_table[out->usecase],
3994 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3995
3996 if (status == CARD_STATUS_OFFLINE)
3997 out_on_error(stream);
3998
3999 return;
4000}
4001
Kevin Rocardfce19002017-08-07 19:21:36 -07004002static int get_alive_usb_card(struct str_parms* parms) {
4003 int card;
4004 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4005 !audio_extn_usb_alive(card)) {
4006 return card;
4007 }
4008 return -ENODEV;
4009}
4010
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004011static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4012{
4013 struct stream_out *out = (struct stream_out *)stream;
4014 struct audio_device *adev = out->dev;
4015 struct str_parms *parms;
4016 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004017 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304018 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004019 bool reconfig = false;
4020 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004021
sangwoobc677242013-08-08 16:53:43 +09004022 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004023 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304025 if (!parms)
4026 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004027 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4028 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004029 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004030 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004031 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004032
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004033 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004034 * When HDMI cable is unplugged the music playback is paused and
4035 * the policy manager sends routing=0. But the audioflinger continues
4036 * to write data until standby time (3sec). As the HDMI core is
4037 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004038 * Avoid this by routing audio to speaker until standby.
4039 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004040 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4041 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304042 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004043 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4044 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004045 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304046 /*
4047 * When A2DP is disconnected the
4048 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004049 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304050 * (3sec). As BT is turned off, the write gets blocked.
4051 * Avoid this by routing audio to speaker until standby.
4052 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004053 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004054 (val == AUDIO_DEVICE_NONE) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004055 !audio_extn_a2dp_source_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304056 val = AUDIO_DEVICE_OUT_SPEAKER;
4057 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304058 /*
4059 * When USB headset is disconnected the music platback paused
4060 * and the policy manager send routing=0. But if the USB is connected
4061 * back before the standby time, AFE is not closed and opened
4062 * when USB is connected back. So routing to speker will guarantee
4063 * AFE reconfiguration and AFE will be opend once USB is connected again
4064 */
4065 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4066 (val == AUDIO_DEVICE_NONE) &&
4067 !audio_extn_usb_connected(parms)) {
4068 val = AUDIO_DEVICE_OUT_SPEAKER;
4069 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304070 /* To avoid a2dp to sco overlapping / BT device improper state
4071 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304072 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304073 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004074 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004075 if (val &
4076 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304077 //combo usecase just by pass a2dp
4078 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304079 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304080 } else {
4081 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4082 /* update device to a2dp and don't route as BT returned error
4083 * However it is still possible a2dp routing called because
4084 * of current active device disconnection (like wired headset)
4085 */
4086 out->devices = val;
4087 pthread_mutex_unlock(&out->lock);
4088 pthread_mutex_unlock(&adev->lock);
4089 goto error;
4090 }
4091 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304092 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004093
4094 audio_devices_t new_dev = val;
4095
4096 // Workaround: If routing to an non existing usb device, fail gracefully
4097 // The routing request will otherwise block during 10 second
4098 int card;
4099 if (audio_is_usb_out_device(new_dev) &&
4100 (card = get_alive_usb_card(parms)) >= 0) {
4101
4102 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4103 pthread_mutex_unlock(&adev->lock);
4104 pthread_mutex_unlock(&out->lock);
4105 ret = -ENOSYS;
4106 goto routing_fail;
4107 }
4108
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004109 /*
4110 * select_devices() call below switches all the usecases on the same
4111 * backend to the new device. Refer to check_usecases_codec_backend() in
4112 * the select_devices(). But how do we undo this?
4113 *
4114 * For example, music playback is active on headset (deep-buffer usecase)
4115 * and if we go to ringtones and select a ringtone, low-latency usecase
4116 * will be started on headset+speaker. As we can't enable headset+speaker
4117 * and headset devices at the same time, select_devices() switches the music
4118 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4119 * So when the ringtone playback is completed, how do we undo the same?
4120 *
4121 * We are relying on the out_set_parameters() call on deep-buffer output,
4122 * once the ringtone playback is ended.
4123 * NOTE: We should not check if the current devices are same as new devices.
4124 * Because select_devices() must be called to switch back the music
4125 * playback to headset.
4126 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004127 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004128 audio_devices_t new_dev = val;
4129 bool same_dev = out->devices == new_dev;
4130 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004131
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004132 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004133 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004134 if (adev->mode == AUDIO_MODE_IN_CALL) {
4135 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004136 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4137 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4138 audio_extn_usb_set_service_interval(true /*playback*/,
4139 service_interval,
4140 &reconfig);
4141 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4142 }
4143 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004144 }
4145 } else {
4146 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004147 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004148 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004149 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004150
4151 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004152 if (!same_dev) {
4153 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304154 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4155 adev->perf_lock_opts,
4156 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004157 if (adev->adm_on_routing_change)
4158 adev->adm_on_routing_change(adev->adm_data,
4159 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004160 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304161 if (!bypass_a2dp) {
4162 select_devices(adev, out->usecase);
4163 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004164 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4165 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4166 else
4167 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304168 select_devices(adev, out->usecase);
4169 out->devices = new_dev;
4170 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004171
4172 if (!same_dev) {
4173 // on device switch force swap, lower functions will make sure
4174 // to check if swap is allowed or not.
4175 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304176 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004177 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304178 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4179 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004180 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304181 pthread_mutex_lock(&out->compr_mute_lock);
4182 out->a2dp_compress_mute = false;
4183 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4184 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004185 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4186 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304187 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004188 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004189 }
4190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004191 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004192 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004193
4194 /*handles device and call state changes*/
4195 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004196 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004197 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004198
4199 if (out == adev->primary_output) {
4200 pthread_mutex_lock(&adev->lock);
4201 audio_extn_set_parameters(adev, parms);
4202 pthread_mutex_unlock(&adev->lock);
4203 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004204 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004205 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004206 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004207
4208 audio_extn_dts_create_state_notifier_node(out->usecase);
4209 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4210 popcount(out->channel_mask),
4211 out->playback_started);
4212
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004213 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004214 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004215
Surendar Karkaf51b5842018-04-26 11:28:38 +05304216 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4217 sizeof(value));
4218 if (err >= 0) {
4219 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4220 audio_extn_send_dual_mono_mixing_coefficients(out);
4221 }
4222
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304223 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4224 if (err >= 0) {
4225 strlcpy(out->profile, value, sizeof(out->profile));
4226 ALOGV("updating stream profile with value '%s'", out->profile);
4227 lock_output_stream(out);
4228 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4229 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004230 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304231 out->sample_rate, out->bit_width,
4232 out->channel_mask, out->profile,
4233 &out->app_type_cfg);
4234 pthread_mutex_unlock(&out->lock);
4235 }
4236
Alexy Joseph98988832017-01-13 14:56:59 -08004237 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004238 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4239 // and vendor.audio.hal.output.suspend.supported is set to true
4240 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004241 //check suspend parameter only for low latency and if the property
4242 //is enabled
4243 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4244 ALOGI("%s: got suspend_playback %s", __func__, value);
4245 lock_output_stream(out);
4246 if (!strncmp(value, "false", 5)) {
4247 //suspend_playback=false is supposed to set QOS value back to 75%
4248 //the mixer control sent with value Enable will achieve that
4249 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4250 } else if (!strncmp (value, "true", 4)) {
4251 //suspend_playback=true is supposed to remove QOS value
4252 //resetting the mixer control will set the default value
4253 //for the mixer control which is Disable and this removes the QOS vote
4254 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4255 } else {
4256 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4257 " got %s", __func__, value);
4258 ret = -1;
4259 }
4260
4261 if (ret != 0) {
4262 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4263 __func__, out->pm_qos_mixer_path, ret);
4264 }
4265
4266 pthread_mutex_unlock(&out->lock);
4267 }
4268 }
4269 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004270 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304271error:
Eric Laurent994a6932013-07-17 11:51:42 -07004272 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004273 return ret;
4274}
4275
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004276static bool stream_get_parameter_channels(struct str_parms *query,
4277 struct str_parms *reply,
4278 audio_channel_mask_t *supported_channel_masks) {
4279 int ret = -1;
4280 char value[512];
4281 bool first = true;
4282 size_t i, j;
4283
4284 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4285 ret = 0;
4286 value[0] = '\0';
4287 i = 0;
4288 while (supported_channel_masks[i] != 0) {
4289 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4290 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4291 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304292 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004293
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304294 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004295 first = false;
4296 break;
4297 }
4298 }
4299 i++;
4300 }
4301 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4302 }
4303 return ret == 0;
4304}
4305
4306static bool stream_get_parameter_formats(struct str_parms *query,
4307 struct str_parms *reply,
4308 audio_format_t *supported_formats) {
4309 int ret = -1;
4310 char value[256];
4311 size_t i, j;
4312 bool first = true;
4313
4314 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4315 ret = 0;
4316 value[0] = '\0';
4317 i = 0;
4318 while (supported_formats[i] != 0) {
4319 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4320 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4321 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304322 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004323 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304324 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004325 first = false;
4326 break;
4327 }
4328 }
4329 i++;
4330 }
4331 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4332 }
4333 return ret == 0;
4334}
4335
4336static bool stream_get_parameter_rates(struct str_parms *query,
4337 struct str_parms *reply,
4338 uint32_t *supported_sample_rates) {
4339
4340 int i;
4341 char value[256];
4342 int ret = -1;
4343 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4344 ret = 0;
4345 value[0] = '\0';
4346 i=0;
4347 int cursor = 0;
4348 while (supported_sample_rates[i]) {
4349 int avail = sizeof(value) - cursor;
4350 ret = snprintf(value + cursor, avail, "%s%d",
4351 cursor > 0 ? "|" : "",
4352 supported_sample_rates[i]);
4353 if (ret < 0 || ret >= avail) {
4354 // if cursor is at the last element of the array
4355 // overwrite with \0 is duplicate work as
4356 // snprintf already put a \0 in place.
4357 // else
4358 // we had space to write the '|' at value[cursor]
4359 // (which will be overwritten) or no space to fill
4360 // the first element (=> cursor == 0)
4361 value[cursor] = '\0';
4362 break;
4363 }
4364 cursor += ret;
4365 ++i;
4366 }
4367 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4368 value);
4369 }
4370 return ret >= 0;
4371}
4372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004373static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4374{
4375 struct stream_out *out = (struct stream_out *)stream;
4376 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004377 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004378 char value[256];
4379 struct str_parms *reply = str_parms_create();
4380 size_t i, j;
4381 int ret;
4382 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004383
4384 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004385 if (reply) {
4386 str_parms_destroy(reply);
4387 }
4388 if (query) {
4389 str_parms_destroy(query);
4390 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004391 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4392 return NULL;
4393 }
4394
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004395 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004396 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4397 if (ret >= 0) {
4398 value[0] = '\0';
4399 i = 0;
4400 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004401 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4402 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004403 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004404 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004405 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004406 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004407 first = false;
4408 break;
4409 }
4410 }
4411 i++;
4412 }
4413 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4414 str = str_parms_to_str(reply);
4415 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004416 voice_extn_out_get_parameters(out, query, reply);
4417 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004418 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004419
Alexy Joseph62142aa2015-11-16 15:10:34 -08004420
4421 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4422 if (ret >= 0) {
4423 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304424 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4425 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004426 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304427 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004428 } else {
4429 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304430 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004431 }
4432 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004433 if (str)
4434 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004435 str = str_parms_to_str(reply);
4436 }
4437
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004438 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4439 if (ret >= 0) {
4440 value[0] = '\0';
4441 i = 0;
4442 first = true;
4443 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004444 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4445 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004446 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004447 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004448 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004449 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004450 first = false;
4451 break;
4452 }
4453 }
4454 i++;
4455 }
4456 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004457 if (str)
4458 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004459 str = str_parms_to_str(reply);
4460 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004461
4462 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4463 if (ret >= 0) {
4464 value[0] = '\0';
4465 i = 0;
4466 first = true;
4467 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004468 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4469 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004470 if (!first) {
4471 strlcat(value, "|", sizeof(value));
4472 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004473 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004474 first = false;
4475 break;
4476 }
4477 }
4478 i++;
4479 }
4480 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4481 if (str)
4482 free(str);
4483 str = str_parms_to_str(reply);
4484 }
4485
Alexy Joseph98988832017-01-13 14:56:59 -08004486 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4487 //only low latency track supports suspend_resume
4488 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004489 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004490 if (str)
4491 free(str);
4492 str = str_parms_to_str(reply);
4493 }
4494
4495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004496 str_parms_destroy(query);
4497 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004498 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004499 return str;
4500}
4501
4502static uint32_t out_get_latency(const struct audio_stream_out *stream)
4503{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004504 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004505 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004506 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004507
Alexy Josephaa54c872014-12-03 02:46:47 -08004508 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304509 lock_output_stream(out);
4510 latency = audio_extn_utils_compress_get_dsp_latency(out);
4511 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004512 } else if ((out->realtime) ||
4513 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004514 // since the buffer won't be filled up faster than realtime,
4515 // return a smaller number
4516 if (out->config.rate)
4517 period_ms = (out->af_period_multiplier * out->config.period_size *
4518 1000) / (out->config.rate);
4519 else
4520 period_ms = 0;
4521 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004522 } else {
4523 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004524 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004525 }
4526
yidongh0515e042017-07-06 15:00:34 +08004527 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004528 latency += audio_extn_a2dp_get_encoder_latency();
4529
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304530 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004531 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004532}
4533
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304534static float AmpToDb(float amplification)
4535{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304536 float db = DSD_VOLUME_MIN_DB;
4537 if (amplification > 0) {
4538 db = 20 * log10(amplification);
4539 if(db < DSD_VOLUME_MIN_DB)
4540 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304541 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304542 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304543}
4544
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304545static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4546 float right)
4547{
4548 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304549 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304550 char mixer_ctl_name[128];
4551 struct audio_device *adev = out->dev;
4552 struct mixer_ctl *ctl;
4553 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4554 PCM_PLAYBACK);
4555
4556 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4557 "Compress Playback %d Volume", pcm_device_id);
4558 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4559 if (!ctl) {
4560 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4561 __func__, mixer_ctl_name);
4562 return -EINVAL;
4563 }
4564 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4565 __func__, mixer_ctl_name, left, right);
4566 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4567 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4568 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4569
4570 return 0;
4571}
4572
Zhou Song2b8f28f2017-09-11 10:51:38 +08004573static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4574 float right)
4575{
4576 struct stream_out *out = (struct stream_out *)stream;
4577 char mixer_ctl_name[] = "App Type Gain";
4578 struct audio_device *adev = out->dev;
4579 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304580 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004581
4582 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4583 if (!ctl) {
4584 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4585 __func__, mixer_ctl_name);
4586 return -EINVAL;
4587 }
4588
4589 set_values[0] = 0; //0: Rx Session 1:Tx Session
4590 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304591 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4592 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004593
4594 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4595 return 0;
4596}
4597
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304598static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
4599 float right)
4600{
4601 struct stream_out *out = (struct stream_out *)stream;
4602 /* Volume control for pcm playback */
4603 if (left != right) {
4604 return -EINVAL;
4605 } else {
4606 char mixer_ctl_name[128];
4607 struct audio_device *adev = out->dev;
4608 struct mixer_ctl *ctl;
4609 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4610 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
4611 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4612 if (!ctl) {
4613 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
4614 return -EINVAL;
4615 }
4616
4617 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
4618 int ret = mixer_ctl_set_value(ctl, 0, volume);
4619 if (ret < 0) {
4620 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
4621 return -EINVAL;
4622 }
4623
4624 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
4625
4626 return 0;
4627 }
4628}
4629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004630static int out_set_volume(struct audio_stream_out *stream, float left,
4631 float right)
4632{
Eric Laurenta9024de2013-04-04 09:19:12 -07004633 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004634 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304635 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004636
Eric Laurenta9024de2013-04-04 09:19:12 -07004637 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4638 /* only take left channel into account: the API is for stereo anyway */
4639 out->muted = (left == 0.0f);
4640 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004641 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304642 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004643 /*
4644 * Set mute or umute on HDMI passthrough stream.
4645 * Only take left channel into account.
4646 * Mute is 0 and unmute 1
4647 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304648 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304649 } else if (out->format == AUDIO_FORMAT_DSD){
4650 char mixer_ctl_name[128] = "DSD Volume";
4651 struct audio_device *adev = out->dev;
4652 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4653
4654 if (!ctl) {
4655 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4656 __func__, mixer_ctl_name);
4657 return -EINVAL;
4658 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304659 volume[0] = (long)(AmpToDb(left));
4660 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304661 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4662 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004663 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304664 pthread_mutex_lock(&out->compr_mute_lock);
4665 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
4666 if (!out->a2dp_compress_mute)
4667 ret = out_set_compr_volume(stream, left, right);
4668 out->volume_l = left;
4669 out->volume_r = right;
4670 pthread_mutex_unlock(&out->compr_mute_lock);
4671 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004672 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004673 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004674 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
4675 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
4676 if (!out->standby) {
4677 audio_extn_utils_send_app_type_gain(out->dev,
4678 out->app_type_cfg.app_type,
4679 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004680 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08004681 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08004682 out->volume_l = left;
4683 out->volume_r = right;
4684 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304685 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05304686 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4687 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304688 /* Volume control for pcm playback */
4689 if (!out->standby)
4690 ret = out_set_pcm_volume(stream, left, right);
4691 else
4692 out->apply_volume = true;
4693
4694 out->volume_l = left;
4695 out->volume_r = right;
4696 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004697 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004699 return -ENOSYS;
4700}
4701
Zhou Songc9672822017-08-16 16:01:39 +08004702static void update_frames_written(struct stream_out *out, size_t bytes)
4703{
4704 size_t bpf = 0;
4705
4706 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4707 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4708 bpf = 1;
4709 else if (!is_offload_usecase(out->usecase))
4710 bpf = audio_bytes_per_sample(out->format) *
4711 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004712
4713 pthread_mutex_lock(&out->position_query_lock);
4714 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004715 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004716 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4717 }
4718 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004719}
4720
Aalique Grahame22e49102018-12-18 14:23:57 -08004721#ifdef NO_AUDIO_OUT
4722static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
4723 const void *buffer __unused, size_t bytes)
4724{
4725 struct stream_out *out = (struct stream_out *)stream;
4726
4727 /* No Output device supported other than BT for playback.
4728 * Sleep for the amount of buffer duration
4729 */
4730 lock_output_stream(out);
4731 usleep(bytes * 1000000 / audio_stream_out_frame_size(
4732 (const struct audio_stream_out *)&out->stream) /
4733 out_get_sample_rate(&out->stream.common));
4734 pthread_mutex_unlock(&out->lock);
4735 return bytes;
4736}
4737#endif
4738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004739static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4740 size_t bytes)
4741{
4742 struct stream_out *out = (struct stream_out *)stream;
4743 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004744 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304745 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004746 const size_t frame_size = audio_stream_out_frame_size(stream);
4747 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004748
Haynes Mathew George380745d2017-10-04 15:27:45 -07004749 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004750 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304751
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304752 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004753
Dhananjay Kumarac341582017-02-23 23:42:25 +05304754 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304755 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304756 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4757 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004758 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304759 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304760 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304761 ALOGD(" %s: sound card is not active/SSR state", __func__);
4762 ret= -EIO;
4763 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304764 }
4765 }
4766
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304767 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304768 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304769 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304770 goto exit;
4771 }
4772
Haynes Mathew George16081042017-05-31 17:16:49 -07004773 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4774 ret = -EINVAL;
4775 goto exit;
4776 }
4777
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304778 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4779 !out->is_iec61937_info_available) {
4780
4781 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4782 out->is_iec61937_info_available = true;
4783 } else if (audio_extn_passthru_is_enabled()) {
4784 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304785 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304786
4787 if((out->format == AUDIO_FORMAT_DTS) ||
4788 (out->format == AUDIO_FORMAT_DTS_HD)) {
4789 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4790 buffer, bytes);
4791 if (ret) {
4792 if (ret != -ENOSYS) {
4793 out->is_iec61937_info_available = false;
4794 ALOGD("iec61937 transmission info not yet updated retry");
4795 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304796 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304797 /* if stream has started and after that there is
4798 * stream config change (iec transmission config)
4799 * then trigger select_device to update backend configuration.
4800 */
4801 out->stream_config_changed = true;
4802 pthread_mutex_lock(&adev->lock);
4803 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304804 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4805 ret = -EINVAL;
4806 goto exit;
4807 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304808 pthread_mutex_unlock(&adev->lock);
4809 out->stream_config_changed = false;
4810 out->is_iec61937_info_available = true;
4811 }
4812 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304813
Garmond Leung317cbf12017-09-13 16:20:50 -07004814 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304815 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4816 (out->is_iec61937_info_available == true)) {
4817 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4818 ret = -EINVAL;
4819 goto exit;
4820 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304821 }
4822 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304823
4824 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004825 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004826 if (!(out->devices &
4827 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304828 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304829 ret = -EIO;
4830 goto exit;
4831 }
4832 }
4833 }
4834
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004835 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004836 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004837 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004838 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4839 ret = voice_extn_compress_voip_start_output_stream(out);
4840 else
4841 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004842 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004843 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004844 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004845 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004846 goto exit;
4847 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304848 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004849 if (last_known_cal_step != -1) {
4850 ALOGD("%s: retry previous failed cal level set", __func__);
4851 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304852 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004853 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304854
4855 if ((out->is_iec61937_info_available == true) &&
4856 (audio_extn_passthru_is_passthrough_stream(out))&&
4857 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4858 ret = -EINVAL;
4859 goto exit;
4860 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05304861 if (out->set_dual_mono)
4862 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004863 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004864
Ashish Jain81eb2a82015-05-13 10:52:34 +05304865 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004866 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304867 adev->is_channel_status_set = true;
4868 }
4869
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004870 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004871 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004872 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004873 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004874 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4875 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304876 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4877 ALOGD("copl(%p):send next track params in gapless", out);
4878 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4879 out->send_next_track_params = false;
4880 out->is_compr_metadata_avail = false;
4881 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004882 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304883 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304884 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004885
Ashish Jain83a6cc22016-06-28 14:34:17 +05304886 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304887 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304888 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304889 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004890 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304891 return -EINVAL;
4892 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304893 audio_format_t dst_format = out->hal_op_format;
4894 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304895
Dieter Luecking5d57def2018-09-07 14:23:37 +02004896 /* prevent division-by-zero */
4897 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
4898 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
4899 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
4900 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05304901 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02004902 ATRACE_END();
4903 return -EINVAL;
4904 }
4905
Ashish Jainf1eaa582016-05-23 20:54:24 +05304906 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4907 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4908
Ashish Jain83a6cc22016-06-28 14:34:17 +05304909 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304910 dst_format,
4911 buffer,
4912 src_format,
4913 frames);
4914
Ashish Jain83a6cc22016-06-28 14:34:17 +05304915 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304916 bytes_to_write);
4917
4918 /*Convert written bytes in audio flinger format*/
4919 if (ret > 0)
4920 ret = ((ret * format_to_bitwidth_table[out->format]) /
4921 format_to_bitwidth_table[dst_format]);
4922 }
4923 } else
4924 ret = compress_write(out->compr, buffer, bytes);
4925
Zhou Songc9672822017-08-16 16:01:39 +08004926 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4927 update_frames_written(out, bytes);
4928
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304929 if (ret < 0)
4930 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08004931 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304932 /*msg to cb thread only if non blocking write is enabled*/
4933 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304934 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004935 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304936 } else if (-ENETRESET == ret) {
4937 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304938 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304939 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304940 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004941 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304942 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004943 }
Ashish Jain5106d362016-05-11 19:23:33 +05304944
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304945 /* Call compr start only when non-zero bytes of data is there to be rendered */
4946 if (!out->playback_started && ret > 0) {
4947 int status = compress_start(out->compr);
4948 if (status < 0) {
4949 ret = status;
4950 ALOGE("%s: compr start failed with err %d", __func__, errno);
4951 goto exit;
4952 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004953 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004954 out->playback_started = 1;
4955 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004956
4957 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4958 popcount(out->channel_mask),
4959 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004960 }
4961 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004962 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004963 return ret;
4964 } else {
4965 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004966 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004967 if (out->muted)
4968 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004969 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
4970 __func__, frames, frame_size, bytes_to_write);
4971
Aalique Grahame22e49102018-12-18 14:23:57 -08004972 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4973#ifndef COMPRESS_VOIP_ENABLED
4974 out->usecase == USECASE_AUDIO_PLAYBACK_VOIP ||
4975#endif
4976 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004977 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4978 int16_t *src = (int16_t *)buffer;
4979 int16_t *dst = (int16_t *)buffer;
4980
4981 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
4982 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08004983 "out_write called for %s use case with wrong properties",
4984 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004985
4986 /*
4987 * FIXME: this can be removed once audio flinger mixer supports
4988 * mono output
4989 */
4990
4991 /*
4992 * Code below goes over each frame in the buffer and adds both
4993 * L and R samples and then divides by 2 to convert to mono
4994 */
4995 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
4996 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
4997 }
4998 bytes_to_write /= 2;
4999 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005000
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305001 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005002
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005003 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005004
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005005 if (out->config.rate)
5006 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5007 out->config.rate;
5008
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005009 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005010 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5011
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005012 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005013 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005014 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305015 out->convert_buffer != NULL) {
5016
5017 memcpy_by_audio_format(out->convert_buffer,
5018 out->hal_op_format,
5019 buffer,
5020 out->hal_ip_format,
5021 out->config.period_size * out->config.channels);
5022
5023 ret = pcm_write(out->pcm, out->convert_buffer,
5024 (out->config.period_size *
5025 out->config.channels *
5026 format_to_bitwidth_table[out->hal_op_format]));
5027 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305028 /*
5029 * To avoid underrun in DSP when the application is not pumping
5030 * data at required rate, check for the no. of bytes and ignore
5031 * pcm_write if it is less than actual buffer size.
5032 * It is a work around to a change in compress VOIP driver.
5033 */
5034 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5035 bytes < (out->config.period_size * out->config.channels *
5036 audio_bytes_per_sample(out->format))) {
5037 size_t voip_buf_size =
5038 out->config.period_size * out->config.channels *
5039 audio_bytes_per_sample(out->format);
5040 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5041 __func__, bytes, voip_buf_size);
5042 usleep(((uint64_t)voip_buf_size - bytes) *
5043 1000000 / audio_stream_out_frame_size(stream) /
5044 out_get_sample_rate(&out->stream.common));
5045 ret = 0;
5046 } else
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005047 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305048 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005049
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005050 release_out_focus(out);
5051
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305052 if (ret < 0)
5053 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005054 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305055 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005056 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005057 }
5058
5059exit:
Zhou Songc9672822017-08-16 16:01:39 +08005060 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305061 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305062 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305063 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005064 pthread_mutex_unlock(&out->lock);
5065
5066 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005067 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005068 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305069 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305070 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305071 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305072 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305073 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305074 out->standby = true;
5075 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305076 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005077 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5078 /* prevent division-by-zero */
5079 uint32_t stream_size = audio_stream_out_frame_size(stream);
5080 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005081
Dieter Luecking5d57def2018-09-07 14:23:37 +02005082 if ((stream_size == 0) || (srate == 0)) {
5083 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5084 ATRACE_END();
5085 return -EINVAL;
5086 }
5087 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5088 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005089 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305090 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005091 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005092 return ret;
5093 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005094 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005095 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005096 return bytes;
5097}
5098
5099static int out_get_render_position(const struct audio_stream_out *stream,
5100 uint32_t *dsp_frames)
5101{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005102 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005103
5104 if (dsp_frames == NULL)
5105 return -EINVAL;
5106
5107 *dsp_frames = 0;
5108 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005109 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305110
5111 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5112 * this operation and adev_close_output_stream(where out gets reset).
5113 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305114 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005115 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305116 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005117 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305118 return 0;
5119 }
5120
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005121 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305122 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305123 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005124 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305125 if (ret < 0)
5126 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005127 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305128 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005129 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305130 if (-ENETRESET == ret) {
5131 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305132 out->card_status = CARD_STATUS_OFFLINE;
5133 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305134 } else if(ret < 0) {
5135 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305136 ret = -EINVAL;
5137 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305138 /*
5139 * Handle corner case where compress session is closed during SSR
5140 * and timestamp is queried
5141 */
5142 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305143 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305144 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305145 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005146 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305147 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305148 pthread_mutex_unlock(&out->lock);
5149 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005150 } else if (audio_is_linear_pcm(out->format)) {
5151 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005152 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005153 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005154 } else
5155 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005156}
5157
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005158static int out_add_audio_effect(const struct audio_stream *stream __unused,
5159 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005160{
5161 return 0;
5162}
5163
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005164static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5165 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005166{
5167 return 0;
5168}
5169
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005170static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5171 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005172{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305173 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005174}
5175
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005176static int out_get_presentation_position(const struct audio_stream_out *stream,
5177 uint64_t *frames, struct timespec *timestamp)
5178{
5179 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305180 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005181 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005182
Ashish Jain5106d362016-05-11 19:23:33 +05305183 /* below piece of code is not guarded against any lock because audioFliner serializes
5184 * this operation and adev_close_output_stream( where out gets reset).
5185 */
5186 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305187 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005188 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305189 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5190 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5191 return 0;
5192 }
5193
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005194 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005195
Ashish Jain5106d362016-05-11 19:23:33 +05305196 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5197 ret = compress_get_tstamp(out->compr, &dsp_frames,
5198 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005199 // Adjustment accounts for A2dp encoder latency with offload usecases
5200 // Note: Encoder latency is returned in ms.
5201 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5202 unsigned long offset =
5203 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5204 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5205 }
Ashish Jain5106d362016-05-11 19:23:33 +05305206 ALOGVV("%s rendered frames %ld sample_rate %d",
5207 __func__, dsp_frames, out->sample_rate);
5208 *frames = dsp_frames;
5209 if (ret < 0)
5210 ret = -errno;
5211 if (-ENETRESET == ret) {
5212 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305213 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305214 ret = -EINVAL;
5215 } else
5216 ret = 0;
5217 /* this is the best we can do */
5218 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005219 } else {
5220 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005221 unsigned int avail;
5222 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5223 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5224 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5225 // This adjustment accounts for buffering after app processor.
5226 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005227 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005228 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005229
Weiyin Jiangd4633762018-03-16 12:05:03 +08005230 // Adjustment accounts for A2dp encoder latency with non offload usecases
5231 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5232 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5233 signed_frames -=
5234 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5235 }
5236
5237 // It would be unusual for this value to be negative, but check just in case ...
5238 if (signed_frames >= 0) {
5239 *frames = signed_frames;
5240 ret = 0;
5241 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005242 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305243 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305244 *frames = out->written;
5245 clock_gettime(CLOCK_MONOTONIC, timestamp);
5246 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005247 }
5248 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005249 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005250 return ret;
5251}
5252
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005253static int out_set_callback(struct audio_stream_out *stream,
5254 stream_callback_t callback, void *cookie)
5255{
5256 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005257 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005258
5259 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005260 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005261 out->client_callback = callback;
5262 out->client_cookie = cookie;
5263 if (out->adsp_hdlr_stream_handle) {
5264 ret = audio_extn_adsp_hdlr_stream_set_callback(
5265 out->adsp_hdlr_stream_handle,
5266 callback,
5267 cookie);
5268 if (ret)
5269 ALOGW("%s:adsp hdlr callback registration failed %d",
5270 __func__, ret);
5271 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005272 pthread_mutex_unlock(&out->lock);
5273 return 0;
5274}
5275
5276static int out_pause(struct audio_stream_out* stream)
5277{
5278 struct stream_out *out = (struct stream_out *)stream;
5279 int status = -ENOSYS;
5280 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005281 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005282 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005283 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005284 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305285 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305286 status = compress_pause(out->compr);
5287
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005288 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005289
Mingming Yin21854652016-04-13 11:54:02 -07005290 if (audio_extn_passthru_is_active()) {
5291 ALOGV("offload use case, pause passthru");
5292 audio_extn_passthru_on_pause(out);
5293 }
5294
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305295 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005296 audio_extn_dts_notify_playback_state(out->usecase, 0,
5297 out->sample_rate, popcount(out->channel_mask),
5298 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005299 }
5300 pthread_mutex_unlock(&out->lock);
5301 }
5302 return status;
5303}
5304
5305static int out_resume(struct audio_stream_out* stream)
5306{
5307 struct stream_out *out = (struct stream_out *)stream;
5308 int status = -ENOSYS;
5309 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005310 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005311 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005312 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005313 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005314 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305315 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305316 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005317 }
5318 if (!status) {
5319 out->offload_state = OFFLOAD_STATE_PLAYING;
5320 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305321 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005322 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5323 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005324 }
5325 pthread_mutex_unlock(&out->lock);
5326 }
5327 return status;
5328}
5329
5330static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5331{
5332 struct stream_out *out = (struct stream_out *)stream;
5333 int status = -ENOSYS;
5334 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005335 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005336 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005337 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5338 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5339 else
5340 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5341 pthread_mutex_unlock(&out->lock);
5342 }
5343 return status;
5344}
5345
5346static int out_flush(struct audio_stream_out* stream)
5347{
5348 struct stream_out *out = (struct stream_out *)stream;
5349 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005350 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005351 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005352 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005353 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5354 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005355 } else {
5356 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5357 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005358 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005359 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005360 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005361 return 0;
5362 }
5363 return -ENOSYS;
5364}
5365
Haynes Mathew George16081042017-05-31 17:16:49 -07005366static int out_stop(const struct audio_stream_out* stream)
5367{
5368 struct stream_out *out = (struct stream_out *)stream;
5369 struct audio_device *adev = out->dev;
5370 int ret = -ENOSYS;
5371
5372 ALOGV("%s", __func__);
5373 pthread_mutex_lock(&adev->lock);
5374 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5375 out->playback_started && out->pcm != NULL) {
5376 pcm_stop(out->pcm);
5377 ret = stop_output_stream(out);
5378 out->playback_started = false;
5379 }
5380 pthread_mutex_unlock(&adev->lock);
5381 return ret;
5382}
5383
5384static int out_start(const struct audio_stream_out* stream)
5385{
5386 struct stream_out *out = (struct stream_out *)stream;
5387 struct audio_device *adev = out->dev;
5388 int ret = -ENOSYS;
5389
5390 ALOGV("%s", __func__);
5391 pthread_mutex_lock(&adev->lock);
5392 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5393 !out->playback_started && out->pcm != NULL) {
5394 ret = start_output_stream(out);
5395 if (ret == 0) {
5396 out->playback_started = true;
5397 }
5398 }
5399 pthread_mutex_unlock(&adev->lock);
5400 return ret;
5401}
5402
5403/*
5404 * Modify config->period_count based on min_size_frames
5405 */
5406static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5407{
5408 int periodCountRequested = (min_size_frames + config->period_size - 1)
5409 / config->period_size;
5410 int periodCount = MMAP_PERIOD_COUNT_MIN;
5411
5412 ALOGV("%s original config.period_size = %d config.period_count = %d",
5413 __func__, config->period_size, config->period_count);
5414
5415 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5416 periodCount *= 2;
5417 }
5418 config->period_count = periodCount;
5419
5420 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5421}
5422
5423static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5424 int32_t min_size_frames,
5425 struct audio_mmap_buffer_info *info)
5426{
5427 struct stream_out *out = (struct stream_out *)stream;
5428 struct audio_device *adev = out->dev;
5429 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005430 unsigned int offset1 = 0;
5431 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005432 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005433 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005434
5435 ALOGV("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305436 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005437 pthread_mutex_lock(&adev->lock);
5438
Sharad Sanglec6f32552018-05-04 16:15:38 +05305439 if (CARD_STATUS_OFFLINE == out->card_status ||
5440 CARD_STATUS_OFFLINE == adev->card_status) {
5441 ALOGW("out->card_status or adev->card_status offline, try again");
5442 ret = -EIO;
5443 goto exit;
5444 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005445 if (info == NULL || min_size_frames == 0) {
5446 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5447 ret = -EINVAL;
5448 goto exit;
5449 }
5450 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5451 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5452 ret = -ENOSYS;
5453 goto exit;
5454 }
5455 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5456 if (out->pcm_device_id < 0) {
5457 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5458 __func__, out->pcm_device_id, out->usecase);
5459 ret = -EINVAL;
5460 goto exit;
5461 }
5462
5463 adjust_mmap_period_count(&out->config, min_size_frames);
5464
5465 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5466 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5467 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5468 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305469 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305470 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5471 out->card_status = CARD_STATUS_OFFLINE;
5472 adev->card_status = CARD_STATUS_OFFLINE;
5473 ret = -EIO;
5474 goto exit;
5475 }
5476
Haynes Mathew George16081042017-05-31 17:16:49 -07005477 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5478 step = "open";
5479 ret = -ENODEV;
5480 goto exit;
5481 }
5482 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5483 if (ret < 0) {
5484 step = "begin";
5485 goto exit;
5486 }
5487 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
5488 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005489 ret = platform_get_mmap_data_fd(adev->platform,
5490 out->pcm_device_id, 0 /*playback*/,
5491 &info->shared_memory_fd,
5492 &mmap_size);
5493 if (ret < 0) {
5494 step = "get_mmap_fd";
5495 goto exit;
5496 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005497 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005498 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005499
5500 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5501 if (ret < 0) {
5502 step = "commit";
5503 goto exit;
5504 }
5505
5506 out->standby = false;
5507 ret = 0;
5508
5509 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5510 __func__, info->shared_memory_address, info->buffer_size_frames);
5511
5512exit:
5513 if (ret != 0) {
5514 if (out->pcm == NULL) {
5515 ALOGE("%s: %s - %d", __func__, step, ret);
5516 } else {
5517 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5518 pcm_close(out->pcm);
5519 out->pcm = NULL;
5520 }
5521 }
5522 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305523 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005524 return ret;
5525}
5526
5527static int out_get_mmap_position(const struct audio_stream_out *stream,
5528 struct audio_mmap_position *position)
5529{
5530 struct stream_out *out = (struct stream_out *)stream;
5531 ALOGVV("%s", __func__);
5532 if (position == NULL) {
5533 return -EINVAL;
5534 }
5535 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005536 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005537 return -ENOSYS;
5538 }
5539 if (out->pcm == NULL) {
5540 return -ENOSYS;
5541 }
5542
5543 struct timespec ts = { 0, 0 };
5544 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5545 if (ret < 0) {
5546 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5547 return ret;
5548 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005549 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005550 return 0;
5551}
5552
5553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005554/** audio_stream_in implementation **/
5555static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5556{
5557 struct stream_in *in = (struct stream_in *)stream;
5558
5559 return in->config.rate;
5560}
5561
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005562static int in_set_sample_rate(struct audio_stream *stream __unused,
5563 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005564{
5565 return -ENOSYS;
5566}
5567
5568static size_t in_get_buffer_size(const struct audio_stream *stream)
5569{
5570 struct stream_in *in = (struct stream_in *)stream;
5571
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005572 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5573 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005574 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5575 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 -07005576 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5577 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305578 else if(audio_extn_cin_attached_usecase(in->usecase))
5579 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005580
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005581 return in->config.period_size * in->af_period_multiplier *
5582 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005583}
5584
5585static uint32_t in_get_channels(const struct audio_stream *stream)
5586{
5587 struct stream_in *in = (struct stream_in *)stream;
5588
5589 return in->channel_mask;
5590}
5591
5592static audio_format_t in_get_format(const struct audio_stream *stream)
5593{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005594 struct stream_in *in = (struct stream_in *)stream;
5595
5596 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005597}
5598
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005599static int in_set_format(struct audio_stream *stream __unused,
5600 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005601{
5602 return -ENOSYS;
5603}
5604
5605static int in_standby(struct audio_stream *stream)
5606{
5607 struct stream_in *in = (struct stream_in *)stream;
5608 struct audio_device *adev = in->dev;
5609 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305610 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5611 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005612 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305613
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005614 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005615 if (!in->standby && in->is_st_session) {
5616 ALOGD("%s: sound trigger pcm stop lab", __func__);
5617 audio_extn_sound_trigger_stop_lab(in);
5618 in->standby = 1;
5619 }
5620
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005621 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005622 if (adev->adm_deregister_stream)
5623 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5624
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005625 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005626 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005627 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005628 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005629 voice_extn_compress_voip_close_input_stream(stream);
5630 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005631 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5632 do_stop = in->capture_started;
5633 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005634 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305635 if (audio_extn_cin_attached_usecase(in->usecase))
5636 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005637 }
5638
5639 if (do_stop) {
Zhou Songa8895042016-07-05 17:54:22 +08005640 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005641 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005642 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005643 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005644 in->pcm = NULL;
5645 }
Aalique Grahame22e49102018-12-18 14:23:57 -08005646 adev->enable_voicerx = false;
5647 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Zhou Songa8895042016-07-05 17:54:22 +08005648 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005649 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08005650 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005651 }
5652 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005653 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005654 return status;
5655}
5656
Aalique Grahame22e49102018-12-18 14:23:57 -08005657static int in_dump(const struct audio_stream *stream,
5658 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005659{
Aalique Grahame22e49102018-12-18 14:23:57 -08005660 struct stream_in *in = (struct stream_in *)stream;
5661
5662 // We try to get the lock for consistency,
5663 // but it isn't necessary for these variables.
5664 // If we're not in standby, we may be blocked on a read.
5665 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
5666 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
5667 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
5668 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
5669
5670 if (locked) {
5671 pthread_mutex_unlock(&in->lock);
5672 }
5673
5674 // dump error info
5675 (void)error_log_dump(
5676 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
5677
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005678 return 0;
5679}
5680
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305681static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5682{
5683 if (!stream || !parms)
5684 return;
5685
5686 struct stream_in *in = (struct stream_in *)stream;
5687 struct audio_device *adev = in->dev;
5688
5689 card_status_t status;
5690 int card;
5691 if (parse_snd_card_status(parms, &card, &status) < 0)
5692 return;
5693
5694 pthread_mutex_lock(&adev->lock);
5695 bool valid_cb = (card == adev->snd_card);
5696 pthread_mutex_unlock(&adev->lock);
5697
5698 if (!valid_cb)
5699 return;
5700
5701 lock_input_stream(in);
5702 if (in->card_status != status)
5703 in->card_status = status;
5704 pthread_mutex_unlock(&in->lock);
5705
5706 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5707 use_case_table[in->usecase],
5708 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5709
5710 // a better solution would be to report error back to AF and let
5711 // it put the stream to standby
5712 if (status == CARD_STATUS_OFFLINE)
5713 in_standby(&in->stream.common);
5714
5715 return;
5716}
5717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005718static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5719{
5720 struct stream_in *in = (struct stream_in *)stream;
5721 struct audio_device *adev = in->dev;
5722 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005723 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005724 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005725
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305726 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005727 parms = str_parms_create_str(kvpairs);
5728
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305729 if (!parms)
5730 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005731 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005732 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005733
5734 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5735 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005736 val = atoi(value);
5737 /* no audio source uses val == 0 */
5738 if ((in->source != val) && (val != 0)) {
5739 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005740 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5741 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5742 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005743 (in->config.rate == 8000 || in->config.rate == 16000 ||
5744 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005745 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005746 err = voice_extn_compress_voip_open_input_stream(in);
5747 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005748 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005749 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005750 }
5751 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005752 }
5753 }
5754
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005755 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5756 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005757 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005758 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5759
5760 // Workaround: If routing to an non existing usb device, fail gracefully
5761 // The routing request will otherwise block during 10 second
5762 int card;
5763 if (audio_is_usb_in_device(val) &&
5764 (card = get_alive_usb_card(parms)) >= 0) {
5765
5766 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5767 ret = -ENOSYS;
5768 } else {
5769
5770 in->device = val;
5771 /* If recording is in progress, change the tx device to new device */
5772 if (!in->standby && !in->is_st_session) {
5773 ALOGV("update input routing change");
5774 // inform adm before actual routing to prevent glitches.
5775 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005776 adev->adm_on_routing_change(adev->adm_data,
5777 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005778 ret = select_devices(adev, in->usecase);
5779 }
5780 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005781 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005782 }
5783 }
5784
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305785 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5786 if (err >= 0) {
5787 strlcpy(in->profile, value, sizeof(in->profile));
5788 ALOGV("updating stream profile with value '%s'", in->profile);
5789 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5790 &adev->streams_input_cfg_list,
5791 in->device, in->flags, in->format,
5792 in->sample_rate, in->bit_width,
5793 in->profile, &in->app_type_cfg);
5794 }
5795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005796 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005797 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005798
5799 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305800error:
Eric Laurent994a6932013-07-17 11:51:42 -07005801 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005802 return ret;
5803}
5804
5805static char* in_get_parameters(const struct audio_stream *stream,
5806 const char *keys)
5807{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005808 struct stream_in *in = (struct stream_in *)stream;
5809 struct str_parms *query = str_parms_create_str(keys);
5810 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005811 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005812
5813 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005814 if (reply) {
5815 str_parms_destroy(reply);
5816 }
5817 if (query) {
5818 str_parms_destroy(query);
5819 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005820 ALOGE("in_get_parameters: failed to create query or reply");
5821 return NULL;
5822 }
5823
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005824 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005825
5826 voice_extn_in_get_parameters(in, query, reply);
5827
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005828 stream_get_parameter_channels(query, reply,
5829 &in->supported_channel_masks[0]);
5830 stream_get_parameter_formats(query, reply,
5831 &in->supported_formats[0]);
5832 stream_get_parameter_rates(query, reply,
5833 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005834 str = str_parms_to_str(reply);
5835 str_parms_destroy(query);
5836 str_parms_destroy(reply);
5837
5838 ALOGV("%s: exit: returns - %s", __func__, str);
5839 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005840}
5841
Aalique Grahame22e49102018-12-18 14:23:57 -08005842static int in_set_gain(struct audio_stream_in *stream,
5843 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005844{
Aalique Grahame22e49102018-12-18 14:23:57 -08005845 struct stream_in *in = (struct stream_in *)stream;
5846 char mixer_ctl_name[128];
5847 struct mixer_ctl *ctl;
5848 int ctl_value;
5849
5850 ALOGV("%s: gain %f", __func__, gain);
5851
5852 if (stream == NULL)
5853 return -EINVAL;
5854
5855 /* in_set_gain() only used to silence MMAP capture for now */
5856 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
5857 return -ENOSYS;
5858
5859 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
5860
5861 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
5862 if (!ctl) {
5863 ALOGW("%s: Could not get ctl for mixer cmd - %s",
5864 __func__, mixer_ctl_name);
5865 return -ENOSYS;
5866 }
5867
5868 if (gain < RECORD_GAIN_MIN)
5869 gain = RECORD_GAIN_MIN;
5870 else if (gain > RECORD_GAIN_MAX)
5871 gain = RECORD_GAIN_MAX;
5872 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
5873
5874 mixer_ctl_set_value(ctl, 0, ctl_value);
5875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005876 return 0;
5877}
5878
5879static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5880 size_t bytes)
5881{
5882 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305883
5884 if (in == NULL) {
5885 ALOGE("%s: stream_in ptr is NULL", __func__);
5886 return -EINVAL;
5887 }
5888
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005889 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305890 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305891 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005892
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005893 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305894
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005895 if (in->is_st_session) {
5896 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5897 /* Read from sound trigger HAL */
5898 audio_extn_sound_trigger_read(in, buffer, bytes);
5899 pthread_mutex_unlock(&in->lock);
5900 return bytes;
5901 }
5902
Haynes Mathew George16081042017-05-31 17:16:49 -07005903 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5904 ret = -ENOSYS;
5905 goto exit;
5906 }
5907
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005908 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005909 pthread_mutex_lock(&adev->lock);
5910 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5911 ret = voice_extn_compress_voip_start_input_stream(in);
5912 else
5913 ret = start_input_stream(in);
5914 pthread_mutex_unlock(&adev->lock);
5915 if (ret != 0) {
5916 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005917 }
5918 in->standby = 0;
5919 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005920
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005921 // what's the duration requested by the client?
5922 long ns = 0;
5923
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305924 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005925 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5926 in->config.rate;
5927
5928 request_in_focus(in, ns);
5929 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005930
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305931 if (audio_extn_cin_attached_usecase(in->usecase)) {
5932 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5933 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305934 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005935 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305936 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005937 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005938 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005939 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005940 } else if (audio_extn_ffv_get_stream() == in) {
5941 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305942 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005943 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305944 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5945 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5946 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5947 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305948 ret = -EINVAL;
5949 goto exit;
5950 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305951 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305952 ret = -errno;
5953 }
5954 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305955 /* bytes read is always set to bytes for non compress usecases */
5956 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005957 }
5958
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005959 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005960
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005961 /*
5962 * Instead of writing zeroes here, we could trust the hardware
5963 * to always provide zeroes when muted.
5964 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305965 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5966 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005967 memset(buffer, 0, bytes);
5968
5969exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005970 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305971 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005972 pthread_mutex_unlock(&in->lock);
5973
5974 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305975 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305976 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305977 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305978 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305979 in->standby = true;
5980 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305981 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5982 bytes_read = bytes;
5983 memset(buffer, 0, bytes);
5984 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005985 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005986 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305987 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305988 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005989 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305990 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005991}
5992
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005993static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005994{
5995 return 0;
5996}
5997
Aalique Grahame22e49102018-12-18 14:23:57 -08005998static int in_get_capture_position(const struct audio_stream_in *stream,
5999 int64_t *frames, int64_t *time)
6000{
6001 if (stream == NULL || frames == NULL || time == NULL) {
6002 return -EINVAL;
6003 }
6004 struct stream_in *in = (struct stream_in *)stream;
6005 int ret = -ENOSYS;
6006
6007 lock_input_stream(in);
6008 // note: ST sessions do not close the alsa pcm driver synchronously
6009 // on standby. Therefore, we may return an error even though the
6010 // pcm stream is still opened.
6011 if (in->standby) {
6012 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6013 "%s stream in standby but pcm not NULL for non ST session", __func__);
6014 goto exit;
6015 }
6016 if (in->pcm) {
6017 struct timespec timestamp;
6018 unsigned int avail;
6019 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6020 *frames = in->frames_read + avail;
6021 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6022 ret = 0;
6023 }
6024 }
6025exit:
6026 pthread_mutex_unlock(&in->lock);
6027 return ret;
6028}
6029
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006030static int add_remove_audio_effect(const struct audio_stream *stream,
6031 effect_handle_t effect,
6032 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006033{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006034 struct stream_in *in = (struct stream_in *)stream;
6035 int status = 0;
6036 effect_descriptor_t desc;
6037
6038 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006039 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6040
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006041 if (status != 0)
6042 return status;
6043
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006044 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006045 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006046 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Aalique Grahame22e49102018-12-18 14:23:57 -08006047 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08006048 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006049 in->enable_aec != enable &&
6050 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
6051 in->enable_aec = enable;
Aalique Grahame22e49102018-12-18 14:23:57 -08006052 if (!enable)
6053 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
6054 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6055 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6056 in->dev->enable_voicerx = enable;
6057 struct audio_usecase *usecase;
6058 struct listnode *node;
6059 list_for_each(node, &in->dev->usecase_list) {
6060 usecase = node_to_item(node, struct audio_usecase, list);
6061 if (usecase->type == PCM_PLAYBACK)
6062 select_devices(in->dev, usecase->id);
6063 }
6064 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006065 if (!in->standby) {
6066 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6067 select_devices(in->dev, in->usecase);
6068 }
6069
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006070 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006071 if (in->enable_ns != enable &&
6072 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
6073 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006074 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006075 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6076 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006077 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6078 select_devices(in->dev, in->usecase);
6079 } else
6080 select_devices(in->dev, in->usecase);
6081 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006082 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006083 pthread_mutex_unlock(&in->dev->lock);
6084 pthread_mutex_unlock(&in->lock);
6085
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006086 return 0;
6087}
6088
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006089static int in_add_audio_effect(const struct audio_stream *stream,
6090 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006091{
Eric Laurent994a6932013-07-17 11:51:42 -07006092 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006093 return add_remove_audio_effect(stream, effect, true);
6094}
6095
6096static int in_remove_audio_effect(const struct audio_stream *stream,
6097 effect_handle_t effect)
6098{
Eric Laurent994a6932013-07-17 11:51:42 -07006099 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006100 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006101}
6102
Haynes Mathew George16081042017-05-31 17:16:49 -07006103static int in_stop(const struct audio_stream_in* stream)
6104{
6105 struct stream_in *in = (struct stream_in *)stream;
6106 struct audio_device *adev = in->dev;
6107
6108 int ret = -ENOSYS;
6109 ALOGV("%s", __func__);
6110 pthread_mutex_lock(&adev->lock);
6111 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6112 in->capture_started && in->pcm != NULL) {
6113 pcm_stop(in->pcm);
6114 ret = stop_input_stream(in);
6115 in->capture_started = false;
6116 }
6117 pthread_mutex_unlock(&adev->lock);
6118 return ret;
6119}
6120
6121static int in_start(const struct audio_stream_in* stream)
6122{
6123 struct stream_in *in = (struct stream_in *)stream;
6124 struct audio_device *adev = in->dev;
6125 int ret = -ENOSYS;
6126
6127 ALOGV("%s in %p", __func__, in);
6128 pthread_mutex_lock(&adev->lock);
6129 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6130 !in->capture_started && in->pcm != NULL) {
6131 if (!in->capture_started) {
6132 ret = start_input_stream(in);
6133 if (ret == 0) {
6134 in->capture_started = true;
6135 }
6136 }
6137 }
6138 pthread_mutex_unlock(&adev->lock);
6139 return ret;
6140}
6141
6142static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6143 int32_t min_size_frames,
6144 struct audio_mmap_buffer_info *info)
6145{
6146 struct stream_in *in = (struct stream_in *)stream;
6147 struct audio_device *adev = in->dev;
6148 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006149 unsigned int offset1 = 0;
6150 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006151 const char *step = "";
6152
6153 pthread_mutex_lock(&adev->lock);
6154 ALOGV("%s in %p", __func__, in);
6155
Sharad Sanglec6f32552018-05-04 16:15:38 +05306156 if (CARD_STATUS_OFFLINE == in->card_status||
6157 CARD_STATUS_OFFLINE == adev->card_status) {
6158 ALOGW("in->card_status or adev->card_status offline, try again");
6159 ret = -EIO;
6160 goto exit;
6161 }
6162
Haynes Mathew George16081042017-05-31 17:16:49 -07006163 if (info == NULL || min_size_frames == 0) {
6164 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6165 ret = -EINVAL;
6166 goto exit;
6167 }
6168 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6169 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6170 ALOGV("%s in %p", __func__, in);
6171 ret = -ENOSYS;
6172 goto exit;
6173 }
6174 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6175 if (in->pcm_device_id < 0) {
6176 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6177 __func__, in->pcm_device_id, in->usecase);
6178 ret = -EINVAL;
6179 goto exit;
6180 }
6181
6182 adjust_mmap_period_count(&in->config, min_size_frames);
6183
6184 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
6185 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
6186 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6187 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306188 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306189 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6190 in->card_status = CARD_STATUS_OFFLINE;
6191 adev->card_status = CARD_STATUS_OFFLINE;
6192 ret = -EIO;
6193 goto exit;
6194 }
6195
Haynes Mathew George16081042017-05-31 17:16:49 -07006196 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6197 step = "open";
6198 ret = -ENODEV;
6199 goto exit;
6200 }
6201
6202 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6203 if (ret < 0) {
6204 step = "begin";
6205 goto exit;
6206 }
6207 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
6208 info->burst_size_frames = in->config.period_size;
6209 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6210
6211 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
6212 info->buffer_size_frames));
6213
6214 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6215 if (ret < 0) {
6216 step = "commit";
6217 goto exit;
6218 }
6219
6220 in->standby = false;
6221 ret = 0;
6222
6223 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6224 __func__, info->shared_memory_address, info->buffer_size_frames);
6225
6226exit:
6227 if (ret != 0) {
6228 if (in->pcm == NULL) {
6229 ALOGE("%s: %s - %d", __func__, step, ret);
6230 } else {
6231 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6232 pcm_close(in->pcm);
6233 in->pcm = NULL;
6234 }
6235 }
6236 pthread_mutex_unlock(&adev->lock);
6237 return ret;
6238}
6239
6240static int in_get_mmap_position(const struct audio_stream_in *stream,
6241 struct audio_mmap_position *position)
6242{
6243 struct stream_in *in = (struct stream_in *)stream;
6244 ALOGVV("%s", __func__);
6245 if (position == NULL) {
6246 return -EINVAL;
6247 }
6248 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6249 return -ENOSYS;
6250 }
6251 if (in->pcm == NULL) {
6252 return -ENOSYS;
6253 }
6254 struct timespec ts = { 0, 0 };
6255 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6256 if (ret < 0) {
6257 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6258 return ret;
6259 }
Naresh Tanniru119d74a2018-11-02 09:49:44 +05306260 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07006261 return 0;
6262}
6263
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306264static int in_get_active_microphones(const struct audio_stream_in *stream,
6265 struct audio_microphone_characteristic_t *mic_array,
6266 size_t *mic_count) {
6267 struct stream_in *in = (struct stream_in *)stream;
6268 struct audio_device *adev = in->dev;
6269 ALOGVV("%s", __func__);
6270
6271 lock_input_stream(in);
6272 pthread_mutex_lock(&adev->lock);
6273 int ret = platform_get_active_microphones(adev->platform,
6274 audio_channel_count_from_in_mask(in->channel_mask),
6275 in->usecase, mic_array, mic_count);
6276 pthread_mutex_unlock(&adev->lock);
6277 pthread_mutex_unlock(&in->lock);
6278
6279 return ret;
6280}
6281
6282static int adev_get_microphones(const struct audio_hw_device *dev,
6283 struct audio_microphone_characteristic_t *mic_array,
6284 size_t *mic_count) {
6285 struct audio_device *adev = (struct audio_device *)dev;
6286 ALOGVV("%s", __func__);
6287
6288 pthread_mutex_lock(&adev->lock);
6289 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6290 pthread_mutex_unlock(&adev->lock);
6291
6292 return ret;
6293}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306294int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006295 audio_io_handle_t handle,
6296 audio_devices_t devices,
6297 audio_output_flags_t flags,
6298 struct audio_config *config,
6299 struct audio_stream_out **stream_out,
6300 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006301{
6302 struct audio_device *adev = (struct audio_device *)dev;
6303 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306304 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006305 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006306 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306307 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006308 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6309 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6310 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6311 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006312
kunleizdff872d2018-08-20 14:40:33 +08006313 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006314 is_usb_dev = false;
6315 devices = AUDIO_DEVICE_OUT_SPEAKER;
6316 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6317 __func__, devices);
6318 }
6319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006320 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006322 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6323
Mingming Yin3a941d42016-02-17 18:08:05 -08006324 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6325 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306326 devices, flags, &out->stream);
6327
6328
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006329 if (!out) {
6330 return -ENOMEM;
6331 }
6332
Haynes Mathew George204045b2015-02-25 20:32:03 -08006333 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006334 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306335 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006336 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006337 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6338
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006339 if (devices == AUDIO_DEVICE_NONE)
6340 devices = AUDIO_DEVICE_OUT_SPEAKER;
6341
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006342 out->flags = flags;
6343 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006344 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006345 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006346 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306347 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306348 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6349 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6350 else
6351 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006352 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006353 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006354 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306355 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306356 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306357 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006358 out->hal_output_suspend_supported = 0;
6359 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05306360 out->set_dual_mono = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006361
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306362 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306363 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006364 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6365
Aalique Grahame22e49102018-12-18 14:23:57 -08006366 if (direct_dev &&
6367 (audio_is_linear_pcm(out->format) ||
6368 config->format == AUDIO_FORMAT_DEFAULT) &&
6369 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
6370 audio_format_t req_format = config->format;
6371 audio_channel_mask_t req_channel_mask = config->channel_mask;
6372 uint32_t req_sample_rate = config->sample_rate;
6373
6374 pthread_mutex_lock(&adev->lock);
6375 if (is_hdmi) {
6376 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6377 ret = read_hdmi_sink_caps(out);
6378 if (config->sample_rate == 0)
6379 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6380 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6381 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
6382 if (config->format == AUDIO_FORMAT_DEFAULT)
6383 config->format = AUDIO_FORMAT_PCM_16_BIT;
6384 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006385 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6386 &config->format,
6387 &out->supported_formats[0],
6388 MAX_SUPPORTED_FORMATS,
6389 &config->channel_mask,
6390 &out->supported_channel_masks[0],
6391 MAX_SUPPORTED_CHANNEL_MASKS,
6392 &config->sample_rate,
6393 &out->supported_sample_rates[0],
6394 MAX_SUPPORTED_SAMPLE_RATES);
6395 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006396 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006397
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006398 pthread_mutex_unlock(&adev->lock);
6399 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006400 if (ret == -ENOSYS) {
6401 /* ignore and go with default */
6402 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08006403 }
6404 // For MMAP NO IRQ, allow conversions in ADSP
6405 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
6406 goto error_open;
6407 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006408 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006409 goto error_open;
6410 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006411
6412 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
6413 config->sample_rate = req_sample_rate;
6414 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
6415 config->channel_mask = req_channel_mask;
6416 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
6417 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08006418 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006419
6420 out->sample_rate = config->sample_rate;
6421 out->channel_mask = config->channel_mask;
6422 out->format = config->format;
6423 if (is_hdmi) {
6424 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6425 out->config = pcm_config_hdmi_multi;
6426 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6427 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6428 out->config = pcm_config_mmap_playback;
6429 out->stream.start = out_start;
6430 out->stream.stop = out_stop;
6431 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6432 out->stream.get_mmap_position = out_get_mmap_position;
6433 } else {
6434 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6435 out->config = pcm_config_hifi;
6436 }
6437
6438 out->config.rate = out->sample_rate;
6439 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6440 if (is_hdmi) {
6441 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6442 audio_bytes_per_sample(out->format));
6443 }
6444 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08006445 }
6446
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006447 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07006448#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006449 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6450 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6451 out->sample_rate == 32000 || out->sample_rate == 48000)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08006452 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6453 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006454 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
Aalique Grahame22e49102018-12-18 14:23:57 -08006455 out->format = AUDIO_FORMAT_PCM_16_BIT;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006456
6457 out->config = default_pcm_config_voip_copp;
6458 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6459 out->config.rate = out->sample_rate;
6460
6461#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05306462 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006463 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08006464 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006465 ret = voice_extn_compress_voip_open_output_stream(out);
6466 if (ret != 0) {
6467 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6468 __func__, ret);
6469 goto error_open;
6470 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006471#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006472 } else if (audio_is_linear_pcm(out->format) &&
6473 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6474 out->channel_mask = config->channel_mask;
6475 out->sample_rate = config->sample_rate;
6476 out->format = config->format;
6477 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6478 // does this change?
6479 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6480 out->config.rate = config->sample_rate;
6481 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6482 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6483 audio_bytes_per_sample(config->format));
6484 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006485 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306486 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306487 pthread_mutex_lock(&adev->lock);
6488 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6489 pthread_mutex_unlock(&adev->lock);
6490
6491 // reject offload during card offline to allow
6492 // fallback to s/w paths
6493 if (offline) {
6494 ret = -ENODEV;
6495 goto error_open;
6496 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006497
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006498 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6499 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6500 ALOGE("%s: Unsupported Offload information", __func__);
6501 ret = -EINVAL;
6502 goto error_open;
6503 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006504
Atul Khare3fa6e542017-08-09 00:56:17 +05306505 if (config->offload_info.format == 0)
6506 config->offload_info.format = config->format;
6507 if (config->offload_info.sample_rate == 0)
6508 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006509
Mingming Yin90310102013-11-13 16:57:00 -08006510 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306511 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006512 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006513 ret = -EINVAL;
6514 goto error_open;
6515 }
6516
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006517 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6518 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6519 (audio_extn_passthru_is_passthrough_stream(out)) &&
6520 !((config->sample_rate == 48000) ||
6521 (config->sample_rate == 96000) ||
6522 (config->sample_rate == 192000))) {
6523 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6524 __func__, config->sample_rate, config->offload_info.format);
6525 ret = -EINVAL;
6526 goto error_open;
6527 }
6528
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006529 out->compr_config.codec = (struct snd_codec *)
6530 calloc(1, sizeof(struct snd_codec));
6531
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006532 if (!out->compr_config.codec) {
6533 ret = -ENOMEM;
6534 goto error_open;
6535 }
6536
Dhananjay Kumarac341582017-02-23 23:42:25 +05306537 out->stream.pause = out_pause;
6538 out->stream.resume = out_resume;
6539 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306540 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306541 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006542 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306543 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006544 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306545 } else {
6546 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6547 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006548 }
vivek mehta446c3962015-09-14 10:57:35 -07006549
6550 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006551 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6552 config->format == 0 && config->sample_rate == 0 &&
6553 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006554 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006555 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6556 } else {
6557 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6558 ret = -EEXIST;
6559 goto error_open;
6560 }
vivek mehta446c3962015-09-14 10:57:35 -07006561 }
6562
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006563 if (config->offload_info.channel_mask)
6564 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006565 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006566 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006567 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006568 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306569 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006570 ret = -EINVAL;
6571 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006572 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006573
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006574 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006575 out->sample_rate = config->offload_info.sample_rate;
6576
Mingming Yin3ee55c62014-08-04 14:23:35 -07006577 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006578
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306579 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306580 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306581 audio_extn_dolby_send_ddp_endp_params(adev);
6582 audio_extn_dolby_set_dmid(adev);
6583 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006584
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006585 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006586 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006587 out->compr_config.codec->bit_rate =
6588 config->offload_info.bit_rate;
6589 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306590 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006591 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306592 /* Update bit width only for non passthrough usecases.
6593 * For passthrough usecases, the output will always be opened @16 bit
6594 */
6595 if (!audio_extn_passthru_is_passthrough_stream(out))
6596 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306597
6598 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6599 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6600 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6601
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006602 /*TODO: Do we need to change it for passthrough */
6603 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006604
Manish Dewangana6fc5442015-08-24 20:30:31 +05306605 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6606 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306607 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306608 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306609 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6610 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306611
6612 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6613 AUDIO_FORMAT_PCM) {
6614
6615 /*Based on platform support, configure appropriate alsa format for corresponding
6616 *hal input format.
6617 */
6618 out->compr_config.codec->format = hal_format_to_alsa(
6619 config->offload_info.format);
6620
Ashish Jain83a6cc22016-06-28 14:34:17 +05306621 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306622 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306623 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306624
Dhananjay Kumarac341582017-02-23 23:42:25 +05306625 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306626 *hal input format and alsa format might differ based on platform support.
6627 */
6628 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306629 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306630
6631 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6632
6633 /* Check if alsa session is configured with the same format as HAL input format,
6634 * if not then derive correct fragment size needed to accomodate the
6635 * conversion of HAL input format to alsa format.
6636 */
6637 audio_extn_utils_update_direct_pcm_fragment_size(out);
6638
6639 /*if hal input and output fragment size is different this indicates HAL input format is
6640 *not same as the alsa format
6641 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306642 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306643 /*Allocate a buffer to convert input data to the alsa configured format.
6644 *size of convert buffer is equal to the size required to hold one fragment size
6645 *worth of pcm data, this is because flinger does not write more than fragment_size
6646 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306647 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6648 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306649 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6650 ret = -ENOMEM;
6651 goto error_open;
6652 }
6653 }
6654 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6655 out->compr_config.fragment_size =
6656 audio_extn_passthru_get_buffer_size(&config->offload_info);
6657 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6658 } else {
6659 out->compr_config.fragment_size =
6660 platform_get_compress_offload_buffer_size(&config->offload_info);
6661 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6662 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006663
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306664 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6665 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6666 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006667 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306668 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006669
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306670 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6671 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6672 }
6673
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006674 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6675 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006676
Manish Dewangan69426c82017-01-30 17:35:36 +05306677 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6678 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6679 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6680 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6681 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6682 } else {
6683 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6684 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006685
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306686 memset(&out->channel_map_param, 0,
6687 sizeof(struct audio_out_channel_map_param));
6688
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006689 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306690 out->send_next_track_params = false;
6691 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006692 out->offload_state = OFFLOAD_STATE_IDLE;
6693 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006694 out->writeAt.tv_sec = 0;
6695 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006696
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006697 audio_extn_dts_create_state_notifier_node(out->usecase);
6698
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006699 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6700 __func__, config->offload_info.version,
6701 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306702
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306703 /* Check if DSD audio format is supported in codec
6704 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306705 */
6706
6707 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306708 (!platform_check_codec_dsd_support(adev->platform) ||
6709 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306710 ret = -EINVAL;
6711 goto error_open;
6712 }
6713
Ashish Jain5106d362016-05-11 19:23:33 +05306714 /* Disable gapless if any of the following is true
6715 * passthrough playback
6716 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306717 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306718 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306719 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306720 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006721 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306722 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306723 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306724 check_and_set_gapless_mode(adev, false);
6725 } else
6726 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006727
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306728 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006729 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6730 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306731 if (config->format == AUDIO_FORMAT_DSD) {
6732 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6733 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6734 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006735
6736 create_offload_callback_thread(out);
6737
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006738 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006739 switch (config->sample_rate) {
6740 case 0:
6741 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6742 break;
6743 case 8000:
6744 case 16000:
6745 case 48000:
6746 out->sample_rate = config->sample_rate;
6747 break;
6748 default:
6749 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
6750 config->sample_rate);
6751 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6752 ret = -EINVAL;
6753 goto error_open;
6754 }
6755 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6756 switch (config->channel_mask) {
6757 case AUDIO_CHANNEL_NONE:
6758 case AUDIO_CHANNEL_OUT_STEREO:
6759 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6760 break;
6761 default:
6762 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
6763 config->channel_mask);
6764 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6765 ret = -EINVAL;
6766 goto error_open;
6767 }
6768 switch (config->format) {
6769 case AUDIO_FORMAT_DEFAULT:
6770 case AUDIO_FORMAT_PCM_16_BIT:
6771 out->format = AUDIO_FORMAT_PCM_16_BIT;
6772 break;
6773 default:
6774 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
6775 config->format);
6776 config->format = AUDIO_FORMAT_PCM_16_BIT;
6777 ret = -EINVAL;
6778 goto error_open;
6779 }
6780
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306781 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006782 if (ret != 0) {
6783 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006784 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006785 goto error_open;
6786 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006787 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08006788 switch (config->sample_rate) {
6789 case 0:
6790 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
6791 break;
6792 case 8000:
6793 case 16000:
6794 case 48000:
6795 out->sample_rate = config->sample_rate;
6796 break;
6797 default:
6798 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
6799 config->sample_rate);
6800 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6801 ret = -EINVAL;
6802 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006803 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006804 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6805 switch (config->channel_mask) {
6806 case AUDIO_CHANNEL_NONE:
6807 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6808 break;
6809 case AUDIO_CHANNEL_OUT_STEREO:
6810 out->channel_mask = config->channel_mask;
6811 break;
6812 default:
6813 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
6814 config->channel_mask);
6815 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6816 ret = -EINVAL;
6817 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006818 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006819 switch (config->format) {
6820 case AUDIO_FORMAT_DEFAULT:
6821 out->format = AUDIO_FORMAT_PCM_16_BIT;
6822 break;
6823 case AUDIO_FORMAT_PCM_16_BIT:
6824 out->format = config->format;
6825 break;
6826 default:
6827 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
6828 config->format);
6829 config->format = AUDIO_FORMAT_PCM_16_BIT;
6830 ret = -EINVAL;
6831 break;
6832 }
6833 if (ret != 0)
6834 goto error_open;
6835
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006836 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
6837 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08006838 out->config.rate = out->sample_rate;
6839 out->config.channels =
6840 audio_channel_count_from_out_mask(out->channel_mask);
6841 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006842 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006843 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05306844 unsigned int channels = 0;
6845 /*Update config params to default if not set by the caller*/
6846 if (config->sample_rate == 0)
6847 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6848 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6849 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6850 if (config->format == AUDIO_FORMAT_DEFAULT)
6851 config->format = AUDIO_FORMAT_PCM_16_BIT;
6852
6853 channels = audio_channel_count_from_out_mask(out->channel_mask);
6854
Varun Balaraje49253e2017-07-06 19:48:56 +05306855 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6856 out->usecase = get_interactive_usecase(adev);
6857 out->config = pcm_config_low_latency;
6858 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306859 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006860 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6861 out->flags);
6862 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006863 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6864 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6865 out->config = pcm_config_mmap_playback;
6866 out->stream.start = out_start;
6867 out->stream.stop = out_stop;
6868 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6869 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306870 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6871 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006872 out->hal_output_suspend_supported =
6873 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6874 out->dynamic_pm_qos_config_supported =
6875 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6876 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006877 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6878 } else {
6879 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6880 //the mixer path will be a string similar to "low-latency-playback resume"
6881 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6882 strlcat(out->pm_qos_mixer_path,
6883 " resume", MAX_MIXER_PATH_LEN);
6884 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6885 out->pm_qos_mixer_path);
6886 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306887 out->config = pcm_config_low_latency;
6888 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6889 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6890 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306891 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6892 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6893 if (out->config.period_size <= 0) {
6894 ALOGE("Invalid configuration period size is not valid");
6895 ret = -EINVAL;
6896 goto error_open;
6897 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006898 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
6899 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
6900 out->config = pcm_config_deep_buffer;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306901 } else {
6902 /* primary path is the default path selected if no other outputs are available/suitable */
6903 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6904 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6905 }
6906 out->hal_ip_format = format = out->format;
6907 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6908 out->hal_op_format = pcm_format_to_hal(out->config.format);
6909 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6910 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006911 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306912 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306913 if (out->hal_ip_format != out->hal_op_format) {
6914 uint32_t buffer_size = out->config.period_size *
6915 format_to_bitwidth_table[out->hal_op_format] *
6916 out->config.channels;
6917 out->convert_buffer = calloc(1, buffer_size);
6918 if (out->convert_buffer == NULL){
6919 ALOGE("Allocation failed for convert buffer for size %d",
6920 out->compr_config.fragment_size);
6921 ret = -ENOMEM;
6922 goto error_open;
6923 }
6924 ALOGD("Convert buffer allocated of size %d", buffer_size);
6925 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006926 }
6927
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006928 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6929 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306930
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006931 /* TODO remove this hardcoding and check why width is zero*/
6932 if (out->bit_width == 0)
6933 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306934 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006935 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006936 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306937 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306938 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006939 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6940 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6941 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006942 if(adev->primary_output == NULL)
6943 adev->primary_output = out;
6944 else {
6945 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006946 ret = -EEXIST;
6947 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006948 }
6949 }
6950
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006951 /* Check if this usecase is already existing */
6952 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006953 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6954 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006955 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006956 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006957 ret = -EEXIST;
6958 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006959 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006960
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006961 pthread_mutex_unlock(&adev->lock);
6962
6963 out->stream.common.get_sample_rate = out_get_sample_rate;
6964 out->stream.common.set_sample_rate = out_set_sample_rate;
6965 out->stream.common.get_buffer_size = out_get_buffer_size;
6966 out->stream.common.get_channels = out_get_channels;
6967 out->stream.common.get_format = out_get_format;
6968 out->stream.common.set_format = out_set_format;
6969 out->stream.common.standby = out_standby;
6970 out->stream.common.dump = out_dump;
6971 out->stream.common.set_parameters = out_set_parameters;
6972 out->stream.common.get_parameters = out_get_parameters;
6973 out->stream.common.add_audio_effect = out_add_audio_effect;
6974 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6975 out->stream.get_latency = out_get_latency;
6976 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08006977#ifdef NO_AUDIO_OUT
6978 out->stream.write = out_write_for_no_output;
6979#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006980 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08006981#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006982 out->stream.get_render_position = out_get_render_position;
6983 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006984 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006985
Haynes Mathew George16081042017-05-31 17:16:49 -07006986 if (out->realtime)
6987 out->af_period_multiplier = af_period_multiplier;
6988 else
6989 out->af_period_multiplier = 1;
6990
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006991 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006992 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006993 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006994
6995 config->format = out->stream.common.get_format(&out->stream.common);
6996 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6997 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05306998 register_format(out->format, out->supported_formats);
6999 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7000 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007001
Aalique Grahame22e49102018-12-18 14:23:57 -08007002 out->error_log = error_log_create(
7003 ERROR_LOG_ENTRIES,
7004 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7005
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307006 /*
7007 By locking output stream before registering, we allow the callback
7008 to update stream's state only after stream's initial state is set to
7009 adev state.
7010 */
7011 lock_output_stream(out);
7012 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7013 pthread_mutex_lock(&adev->lock);
7014 out->card_status = adev->card_status;
7015 pthread_mutex_unlock(&adev->lock);
7016 pthread_mutex_unlock(&out->lock);
7017
Aalique Grahame22e49102018-12-18 14:23:57 -08007018 stream_app_type_cfg_init(&out->app_type_cfg);
7019
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007020 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307021 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007022 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007023
7024 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7025 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7026 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007027 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307028 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007029 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007030 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05307031 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007032 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
7033 out->usecase, PCM_PLAYBACK);
7034 hdlr_stream_cfg.flags = out->flags;
7035 hdlr_stream_cfg.type = PCM_PLAYBACK;
7036 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
7037 &hdlr_stream_cfg);
7038 if (ret) {
7039 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
7040 out->adsp_hdlr_stream_handle = NULL;
7041 }
7042 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05307043 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07007044 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07007045 if (ret < 0) {
7046 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
7047 out->ip_hdlr_handle = NULL;
7048 }
7049 }
Eric Laurent994a6932013-07-17 11:51:42 -07007050 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007051 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007052
7053error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05307054 if (out->convert_buffer)
7055 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007056 free(out);
7057 *stream_out = NULL;
7058 ALOGD("%s: exit: ret %d", __func__, ret);
7059 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007060}
7061
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307062void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007063 struct audio_stream_out *stream)
7064{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007065 struct stream_out *out = (struct stream_out *)stream;
7066 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007067 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007068
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007069 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307070
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307071 // must deregister from sndmonitor first to prevent races
7072 // between the callback and close_stream
7073 audio_extn_snd_mon_unregister_listener(out);
7074
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007075 /* close adsp hdrl session before standby */
7076 if (out->adsp_hdlr_stream_handle) {
7077 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
7078 if (ret)
7079 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
7080 out->adsp_hdlr_stream_handle = NULL;
7081 }
7082
Manish Dewangan21a850a2017-08-14 12:03:55 +05307083 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07007084 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
7085 out->ip_hdlr_handle = NULL;
7086 }
7087
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007088 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307089 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007090 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307091 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307092 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007093 if(ret != 0)
7094 ALOGE("%s: Compress voip output cannot be closed, error:%d",
7095 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007096 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007097 out_standby(&stream->common);
7098
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007099 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007100 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007101 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007102 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007103 if (out->compr_config.codec != NULL)
7104 free(out->compr_config.codec);
7105 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007106
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307107 out->a2dp_compress_mute = false;
7108
Varun Balaraje49253e2017-07-06 19:48:56 +05307109 if (is_interactive_usecase(out->usecase))
7110 free_interactive_usecase(adev, out->usecase);
7111
Ashish Jain83a6cc22016-06-28 14:34:17 +05307112 if (out->convert_buffer != NULL) {
7113 free(out->convert_buffer);
7114 out->convert_buffer = NULL;
7115 }
7116
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007117 if (adev->voice_tx_output == out)
7118 adev->voice_tx_output = NULL;
7119
Aalique Grahame22e49102018-12-18 14:23:57 -08007120 error_log_destroy(out->error_log);
7121 out->error_log = NULL;
7122
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05307123 if (adev->primary_output == out)
7124 adev->primary_output = NULL;
7125
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007126 pthread_cond_destroy(&out->cond);
7127 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007128 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07007129 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007130}
7131
7132static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
7133{
7134 struct audio_device *adev = (struct audio_device *)dev;
7135 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007136 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007137 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007138 int ret;
7139 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007140 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007141
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007142 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007143 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007144
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307145 if (!parms)
7146 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307147
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307148 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
7149 if (ret >= 0) {
7150 /* When set to false, HAL should disable EC and NS */
7151 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7152 adev->bt_sco_on = true;
7153 else
7154 adev->bt_sco_on = false;
7155 }
7156
Naresh Tanniru4c630392014-05-12 01:05:52 +05307157 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007158 status = voice_set_parameters(adev, parms);
7159 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007160 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007161
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007162 status = platform_set_parameters(adev->platform, parms);
7163 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007164 goto done;
7165
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007166 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
7167 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07007168 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007169 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7170 adev->bluetooth_nrec = true;
7171 else
7172 adev->bluetooth_nrec = false;
7173 }
7174
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007175 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
7176 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007177 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7178 adev->screen_off = false;
7179 else
7180 adev->screen_off = true;
7181 }
7182
Aalique Grahame22e49102018-12-18 14:23:57 -08007183#ifndef MAXXAUDIO_QDSP_ENABLED
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007184 ret = str_parms_get_int(parms, "rotation", &val);
7185 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007186 bool reverse_speakers = false;
7187 switch(val) {
7188 // FIXME: note that the code below assumes that the speakers are in the correct placement
7189 // relative to the user when the device is rotated 90deg from its default rotation. This
7190 // assumption is device-specific, not platform-specific like this code.
7191 case 270:
7192 reverse_speakers = true;
7193 break;
7194 case 0:
7195 case 90:
7196 case 180:
7197 break;
7198 default:
7199 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007200 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007201 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007202 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07007203 // check and set swap
7204 // - check if orientation changed and speaker active
7205 // - set rotation and cache the rotation value
7206 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007207 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007208 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007209#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007210
Mingming Yin514a8bc2014-07-29 15:22:21 -07007211 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
7212 if (ret >= 0) {
7213 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7214 adev->bt_wb_speech_enabled = true;
7215 else
7216 adev->bt_wb_speech_enabled = false;
7217 }
7218
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007219 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
7220 if (ret >= 0) {
7221 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307222 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08007223 if (audio_is_output_device(val) &&
7224 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007225 ALOGV("cache new ext disp type and edid");
7226 ret = platform_get_ext_disp_type(adev->platform);
7227 if (ret < 0) {
7228 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05307229 } else {
7230 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007231 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307232 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07007233 /*
7234 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
7235 * Per AudioPolicyManager, USB device is higher priority than WFD.
7236 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
7237 * If WFD use case occupies AFE proxy, it may result unintended behavior while
7238 * starting voice call on USB
7239 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007240 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307241 if (ret >= 0)
7242 audio_extn_usb_add_device(device, atoi(value));
7243
Zhou Song6f862822017-11-06 17:27:57 +08007244 if (!audio_extn_usb_is_tunnel_supported()) {
7245 ALOGV("detected USB connect .. disable proxy");
7246 adev->allow_afe_proxy_usage = false;
7247 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007248 }
7249 }
7250
7251 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
7252 if (ret >= 0) {
7253 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307254 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07007255 /*
7256 * The HDMI / Displayport disconnect handling has been moved to
7257 * audio extension to ensure that its parameters are not
7258 * invalidated prior to updating sysfs of the disconnect event
7259 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
7260 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307261 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007262 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307263 if (ret >= 0)
7264 audio_extn_usb_remove_device(device, atoi(value));
7265
Zhou Song6f862822017-11-06 17:27:57 +08007266 if (!audio_extn_usb_is_tunnel_supported()) {
7267 ALOGV("detected USB disconnect .. enable proxy");
7268 adev->allow_afe_proxy_usage = true;
7269 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007270 }
7271 }
7272
Aalique Grahame22e49102018-12-18 14:23:57 -08007273 audio_extn_hfp_set_parameters(adev, parms);
7274 audio_extn_ma_set_parameters(adev, parms);
7275
7276 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
7277 if (ret >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307278 struct audio_usecase *usecase;
7279 struct listnode *node;
7280 list_for_each(node, &adev->usecase_list) {
7281 usecase = node_to_item(node, struct audio_usecase, list);
7282 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07007283 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307284 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08007285
7286 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307287 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08007288 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307289 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307290 //force device switch to re configure encoder
7291 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307292 audio_extn_a2dp_set_handoff_mode(false);
7293 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307294 break;
7295 }
7296 }
7297 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007298
7299 //handle vr audio setparam
7300 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7301 value, sizeof(value));
7302 if (ret >= 0) {
7303 ALOGI("Setting vr mode to be %s", value);
7304 if (!strncmp(value, "true", 4)) {
7305 adev->vr_audio_mode_enabled = true;
7306 ALOGI("Setting vr mode to true");
7307 } else if (!strncmp(value, "false", 5)) {
7308 adev->vr_audio_mode_enabled = false;
7309 ALOGI("Setting vr mode to false");
7310 } else {
7311 ALOGI("wrong vr mode set");
7312 }
7313 }
7314
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307315 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007316done:
7317 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007318 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307319error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007320 ALOGV("%s: exit with code(%d)", __func__, status);
7321 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007322}
7323
7324static char* adev_get_parameters(const struct audio_hw_device *dev,
7325 const char *keys)
7326{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307327 ALOGD("%s:%s", __func__, keys);
7328
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007329 struct audio_device *adev = (struct audio_device *)dev;
7330 struct str_parms *reply = str_parms_create();
7331 struct str_parms *query = str_parms_create_str(keys);
7332 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05307333 char value[256] = {0};
7334 int ret = 0;
7335
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007336 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007337 if (reply) {
7338 str_parms_destroy(reply);
7339 }
7340 if (query) {
7341 str_parms_destroy(query);
7342 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007343 ALOGE("adev_get_parameters: failed to create query or reply");
7344 return NULL;
7345 }
7346
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007347 //handle vr audio getparam
7348
7349 ret = str_parms_get_str(query,
7350 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7351 value, sizeof(value));
7352
7353 if (ret >= 0) {
7354 bool vr_audio_enabled = false;
7355 pthread_mutex_lock(&adev->lock);
7356 vr_audio_enabled = adev->vr_audio_mode_enabled;
7357 pthread_mutex_unlock(&adev->lock);
7358
7359 ALOGI("getting vr mode to %d", vr_audio_enabled);
7360
7361 if (vr_audio_enabled) {
7362 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7363 "true");
7364 goto exit;
7365 } else {
7366 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7367 "false");
7368 goto exit;
7369 }
7370 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007371
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007372 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007373 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08007374 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08007375 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007376 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05307377 pthread_mutex_unlock(&adev->lock);
7378
Naresh Tannirud7205b62014-06-20 02:54:48 +05307379exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007380 str = str_parms_to_str(reply);
7381 str_parms_destroy(query);
7382 str_parms_destroy(reply);
7383
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307384 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007385 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007386}
7387
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007388static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007389{
7390 return 0;
7391}
7392
7393static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
7394{
Haynes Mathew George5191a852013-09-11 14:19:36 -07007395 int ret;
7396 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08007397
7398 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
7399
Haynes Mathew George5191a852013-09-11 14:19:36 -07007400 pthread_mutex_lock(&adev->lock);
7401 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07007402 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07007403 pthread_mutex_unlock(&adev->lock);
7404 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007405}
7406
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007407static int adev_set_master_volume(struct audio_hw_device *dev __unused,
7408 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007409{
7410 return -ENOSYS;
7411}
7412
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007413static int adev_get_master_volume(struct audio_hw_device *dev __unused,
7414 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007415{
7416 return -ENOSYS;
7417}
7418
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007419static int adev_set_master_mute(struct audio_hw_device *dev __unused,
7420 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007421{
7422 return -ENOSYS;
7423}
7424
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007425static int adev_get_master_mute(struct audio_hw_device *dev __unused,
7426 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007427{
7428 return -ENOSYS;
7429}
7430
7431static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
7432{
7433 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07007434 struct listnode *node;
7435 struct audio_usecase *usecase = NULL;
7436 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007437 pthread_mutex_lock(&adev->lock);
7438 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007439 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007440 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08007441 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07007442 list_for_each(node, &adev->usecase_list) {
7443 usecase = node_to_item(node, struct audio_usecase, list);
7444 if (usecase->type == VOICE_CALL)
7445 break;
7446 }
7447 if (usecase &&
7448 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
7449 ret = audio_extn_usb_check_and_set_svc_int(usecase,
7450 true);
7451 if (ret != 0) {
7452 /* default service interval was successfully updated,
7453 reopen USB backend with new service interval */
7454 check_usecases_codec_backend(adev,
7455 usecase,
7456 usecase->out_snd_device);
7457 }
7458 }
7459
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007460 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07007461 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007462 adev->current_call_output = NULL;
7463 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007464 }
7465 pthread_mutex_unlock(&adev->lock);
7466 return 0;
7467}
7468
7469static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
7470{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007471 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08007472 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007473
7474 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08007475 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007476 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007477
Derek Chend2530072014-11-24 12:39:14 -08007478 if (adev->ext_hw_plugin)
7479 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007480
7481 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007482 pthread_mutex_unlock(&adev->lock);
7483
7484 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007485}
7486
7487static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
7488{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007489 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007490 return 0;
7491}
7492
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007493static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007494 const struct audio_config *config)
7495{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007496 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007497
Aalique Grahame22e49102018-12-18 14:23:57 -08007498 /* Don't know if USB HIFI in this context so use true to be conservative */
7499 if (check_input_parameters(config->sample_rate, config->format, channel_count,
7500 true /*is_usb_hifi */) != 0)
7501 return 0;
7502
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007503 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
7504 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007505}
7506
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007507static bool adev_input_allow_hifi_record(struct audio_device *adev,
7508 audio_devices_t devices,
7509 audio_input_flags_t flags,
7510 audio_source_t source) {
7511 const bool allowed = true;
7512
7513 if (!audio_is_usb_in_device(devices))
7514 return !allowed;
7515
7516 switch (flags) {
7517 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007518 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07007519 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7520 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007521 default:
7522 return !allowed;
7523 }
7524
7525 switch (source) {
7526 case AUDIO_SOURCE_DEFAULT:
7527 case AUDIO_SOURCE_MIC:
7528 case AUDIO_SOURCE_UNPROCESSED:
7529 break;
7530 default:
7531 return !allowed;
7532 }
7533
7534 switch (adev->mode) {
7535 case 0:
7536 break;
7537 default:
7538 return !allowed;
7539 }
7540
7541 return allowed;
7542}
7543
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007544static int adev_update_voice_comm_input_stream(struct stream_in *in,
7545 struct audio_config *config)
7546{
7547 bool valid_rate = (config->sample_rate == 8000 ||
7548 config->sample_rate == 16000 ||
7549 config->sample_rate == 32000 ||
7550 config->sample_rate == 48000);
7551 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
7552
7553#ifndef COMPRESS_VOIP_ENABLED
kunleizd96526c2018-04-09 11:12:32 +08007554 if (valid_rate && valid_ch &&
7555 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007556 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7557 in->config = default_pcm_config_voip_copp;
7558 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
7559 DEFAULT_VOIP_BUF_DURATION_MS,
7560 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
7561 } else {
kunleizbdd9ad02018-04-24 10:53:17 +08007562 ALOGW("%s No valid input in voip, use defaults"
7563 "sample rate %u, channel mask 0x%X",
7564 __func__, config->sample_rate, in->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007565 }
7566 in->config.rate = config->sample_rate;
7567 in->sample_rate = config->sample_rate;
7568#else
7569 //XXX needed for voice_extn_compress_voip_open_input_stream
7570 in->config.rate = config->sample_rate;
7571 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7572 voice_extn_compress_voip_is_active(in->dev)) &&
7573 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7574 valid_rate && valid_ch) {
7575 voice_extn_compress_voip_open_input_stream(in);
7576 // update rate entries to match config from AF
7577 in->config.rate = config->sample_rate;
7578 in->sample_rate = config->sample_rate;
7579 } else {
7580 ALOGW("%s compress voip not active, use defaults", __func__);
7581 }
7582#endif
7583 return 0;
7584}
7585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007586static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007587 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007588 audio_devices_t devices,
7589 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007590 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307591 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007592 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007593 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007594{
7595 struct audio_device *adev = (struct audio_device *)dev;
7596 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007597 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007598 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007599 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05307600 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007601 bool is_usb_dev = audio_is_usb_in_device(devices);
7602 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
7603 devices,
7604 flags,
7605 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307606
kunleizdff872d2018-08-20 14:40:33 +08007607 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007608 is_usb_dev = false;
7609 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
7610 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
7611 __func__, devices);
7612 }
7613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007614 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007615
7616 if (!(is_usb_dev && may_use_hifi_record)) {
7617 if (config->sample_rate == 0)
7618 config->sample_rate = 48000;
7619 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7620 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7621 if (config->format == AUDIO_FORMAT_DEFAULT)
7622 config->format = AUDIO_FORMAT_PCM_16_BIT;
7623
7624 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
7625
Aalique Grahame22e49102018-12-18 14:23:57 -08007626 if (check_input_parameters(config->sample_rate, config->format, channel_count,
7627 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007628 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05307629 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007630
7631 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007632
7633 if (!in) {
7634 ALOGE("failed to allocate input stream");
7635 return -ENOMEM;
7636 }
7637
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307638 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307639 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7640 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007641 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007642 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007644 in->stream.common.get_sample_rate = in_get_sample_rate;
7645 in->stream.common.set_sample_rate = in_set_sample_rate;
7646 in->stream.common.get_buffer_size = in_get_buffer_size;
7647 in->stream.common.get_channels = in_get_channels;
7648 in->stream.common.get_format = in_get_format;
7649 in->stream.common.set_format = in_set_format;
7650 in->stream.common.standby = in_standby;
7651 in->stream.common.dump = in_dump;
7652 in->stream.common.set_parameters = in_set_parameters;
7653 in->stream.common.get_parameters = in_get_parameters;
7654 in->stream.common.add_audio_effect = in_add_audio_effect;
7655 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7656 in->stream.set_gain = in_set_gain;
7657 in->stream.read = in_read;
7658 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08007659 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307660 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007661
7662 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007663 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007664 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007665 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007666 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007667 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007668 in->bit_width = 16;
7669 in->af_period_multiplier = 1;
7670
Aalique Grahame22e49102018-12-18 14:23:57 -08007671 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
7672 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
7673 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
7674 /* Force channel config requested to mono if incall
7675 record is being requested for only uplink/downlink */
7676 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
7677 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7678 ret = -EINVAL;
7679 goto err_open;
7680 }
7681 }
7682
Haynes Mathew George46740472017-10-27 18:40:12 -07007683 /* Update config params with the requested sample rate and channels */
7684 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
7685 (adev->mode != AUDIO_MODE_IN_CALL)) {
7686 ret = -EINVAL;
7687 goto err_open;
7688 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007689
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007690 if (is_usb_dev && may_use_hifi_record) {
7691 /* HiFi record selects an appropriate format, channel, rate combo
7692 depending on sink capabilities*/
7693 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7694 &config->format,
7695 &in->supported_formats[0],
7696 MAX_SUPPORTED_FORMATS,
7697 &config->channel_mask,
7698 &in->supported_channel_masks[0],
7699 MAX_SUPPORTED_CHANNEL_MASKS,
7700 &config->sample_rate,
7701 &in->supported_sample_rates[0],
7702 MAX_SUPPORTED_SAMPLE_RATES);
7703 if (ret != 0) {
7704 ret = -EINVAL;
7705 goto err_open;
7706 }
7707 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007708 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307709 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05307710 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
7711 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
7712 in->config.format = PCM_FORMAT_S32_LE;
7713 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307714 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
7715 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
7716 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
7717 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7718 bool ret_error = false;
7719 in->bit_width = 24;
7720 /* 24 bit is restricted to UNPROCESSED source only,also format supported
7721 from HAL is 24_packed and 8_24
7722 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
7723 24_packed return error indicating supported format is 24_packed
7724 *> In case of any other source requesting 24 bit or float return error
7725 indicating format supported is 16 bit only.
7726
7727 on error flinger will retry with supported format passed
7728 */
7729 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
7730 (source != AUDIO_SOURCE_CAMCORDER)) {
7731 config->format = AUDIO_FORMAT_PCM_16_BIT;
7732 if (config->sample_rate > 48000)
7733 config->sample_rate = 48000;
7734 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07007735 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
7736 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307737 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
7738 ret_error = true;
7739 }
7740
7741 if (ret_error) {
7742 ret = -EINVAL;
7743 goto err_open;
7744 }
7745 }
7746
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007747 in->channel_mask = config->channel_mask;
7748 in->format = config->format;
7749
7750 in->usecase = USECASE_AUDIO_RECORD;
7751 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
7752 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
7753 is_low_latency = true;
7754#if LOW_LATENCY_CAPTURE_USE_CASE
7755 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
7756#endif
7757 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08007758 if (!in->realtime) {
7759 in->config = pcm_config_audio_capture;
7760 frame_size = audio_stream_in_frame_size(&in->stream);
7761 buffer_size = get_input_buffer_size(config->sample_rate,
7762 config->format,
7763 channel_count,
7764 is_low_latency);
7765 in->config.period_size = buffer_size / frame_size;
7766 in->config.rate = config->sample_rate;
7767 in->af_period_multiplier = 1;
7768 } else {
7769 // period size is left untouched for rt mode playback
7770 in->config = pcm_config_audio_capture_rt;
7771 in->af_period_multiplier = af_period_multiplier;
7772 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007773 }
7774
7775 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
7776 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
7777 in->realtime = 0;
7778 in->usecase = USECASE_AUDIO_RECORD_MMAP;
7779 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07007780 in->config.format = pcm_format_from_audio_format(config->format);
Weiyin Jiang7c30c612018-11-27 18:45:53 +08007781 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007782 in->stream.start = in_start;
7783 in->stream.stop = in_stop;
7784 in->stream.create_mmap_buffer = in_create_mmap_buffer;
7785 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007786 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007787 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
7788 } else if (in->realtime) {
7789 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07007790 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007791 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007792 in->sample_rate = in->config.rate;
7793 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07007794 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007795 in->usecase = USECASE_AUDIO_RECORD_HIFI;
7796 in->config = pcm_config_audio_capture;
7797 frame_size = audio_stream_in_frame_size(&in->stream);
7798 buffer_size = get_input_buffer_size(config->sample_rate,
7799 config->format,
7800 channel_count,
7801 false /*is_low_latency*/);
7802 in->config.period_size = buffer_size / frame_size;
7803 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007804 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07007805 switch (config->format) {
7806 case AUDIO_FORMAT_PCM_32_BIT:
7807 in->bit_width = 32;
7808 break;
7809 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
7810 case AUDIO_FORMAT_PCM_8_24_BIT:
7811 in->bit_width = 24;
7812 break;
7813 default:
7814 in->bit_width = 16;
7815 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007816 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007817 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007818 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05307819 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007820 if (config->sample_rate == 0)
7821 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7822 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
7823 config->sample_rate != 8000) {
7824 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7825 ret = -EINVAL;
7826 goto err_open;
7827 }
7828 if (config->format == AUDIO_FORMAT_DEFAULT)
7829 config->format = AUDIO_FORMAT_PCM_16_BIT;
7830 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
7831 config->format = AUDIO_FORMAT_PCM_16_BIT;
7832 ret = -EINVAL;
7833 goto err_open;
7834 }
7835
7836 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
7837 in->config = pcm_config_afe_proxy_record;
7838 in->config.channels = channel_count;
7839 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307840 in->sample_rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08007841 in->af_period_multiplier = 1;
7842 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
7843 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
7844 (config->sample_rate == 8000 ||
7845 config->sample_rate == 16000 ||
7846 config->sample_rate == 32000 ||
7847 config->sample_rate == 48000) &&
7848 channel_count == 1) {
7849 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7850 in->config = pcm_config_audio_capture;
7851 frame_size = audio_stream_in_frame_size(&in->stream);
7852 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
7853 config->sample_rate,
7854 config->format,
7855 channel_count, false /*is_low_latency*/);
7856 in->config.period_size = buffer_size / frame_size;
7857 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
7858 in->config.rate = config->sample_rate;
7859 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07007860 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05307861 int ret_val;
7862 pthread_mutex_lock(&adev->lock);
7863 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
7864 in, config, &channel_mask_updated);
7865 pthread_mutex_unlock(&adev->lock);
7866
7867 if (!ret_val) {
7868 if (channel_mask_updated == true) {
7869 ALOGD("%s: return error to retry with updated channel mask (%#x)",
7870 __func__, config->channel_mask);
7871 ret = -EINVAL;
7872 goto err_open;
7873 }
7874 ALOGD("%s: created multi-channel session succesfully",__func__);
7875 } else if (audio_extn_compr_cap_enabled() &&
7876 audio_extn_compr_cap_format_supported(config->format) &&
7877 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
7878 audio_extn_compr_cap_init(in);
7879 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05307880 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05307881 ret = audio_extn_cin_configure_input_stream(in);
7882 if (ret)
7883 goto err_open;
7884 } else {
7885 in->config = pcm_config_audio_capture;
7886 in->config.rate = config->sample_rate;
7887 in->config.format = pcm_format_from_audio_format(config->format);
7888 in->config.channels = channel_count;
7889 in->sample_rate = config->sample_rate;
7890 in->format = config->format;
7891 frame_size = audio_stream_in_frame_size(&in->stream);
7892 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07007893 config->format,
7894 channel_count,
7895 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02007896 /* prevent division-by-zero */
7897 if (frame_size == 0) {
7898 ALOGE("%s: Error frame_size==0", __func__);
7899 ret = -EINVAL;
7900 goto err_open;
7901 }
7902
Revathi Uddarajud2634032017-12-07 14:42:34 +05307903 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08007904 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007905
Revathi Uddarajud2634032017-12-07 14:42:34 +05307906 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
7907 /* optionally use VOIP usecase depending on config(s) */
7908 ret = adev_update_voice_comm_input_stream(in, config);
7909 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007910
Revathi Uddarajud2634032017-12-07 14:42:34 +05307911 if (ret) {
7912 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
7913 goto err_open;
7914 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007915 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007916 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307917 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7918 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007919 devices, flags, in->format,
7920 in->sample_rate, in->bit_width,
7921 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307922 register_format(in->format, in->supported_formats);
7923 register_channel_mask(in->channel_mask, in->supported_channel_masks);
7924 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307925
Aalique Grahame22e49102018-12-18 14:23:57 -08007926 in->error_log = error_log_create(
7927 ERROR_LOG_ENTRIES,
7928 1000000000 /* aggregate consecutive identical errors within one second */);
7929
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007930 /* This stream could be for sound trigger lab,
7931 get sound trigger pcm if present */
7932 audio_extn_sound_trigger_check_and_get_session(in);
7933
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307934 lock_input_stream(in);
7935 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
7936 pthread_mutex_lock(&adev->lock);
7937 in->card_status = adev->card_status;
7938 pthread_mutex_unlock(&adev->lock);
7939 pthread_mutex_unlock(&in->lock);
7940
Aalique Grahame22e49102018-12-18 14:23:57 -08007941 stream_app_type_cfg_init(&in->app_type_cfg);
7942
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007943 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07007944 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007945 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007946
7947err_open:
7948 free(in);
7949 *stream_in = NULL;
7950 return ret;
7951}
7952
7953static void adev_close_input_stream(struct audio_hw_device *dev,
7954 struct audio_stream_in *stream)
7955{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007956 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007957 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007958 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307959
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307960 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007961
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307962 // must deregister from sndmonitor first to prevent races
7963 // between the callback and close_stream
7964 audio_extn_snd_mon_unregister_listener(stream);
7965
kunleiz8c93ce62018-11-29 15:04:56 +08007966 // Disable echo reference if there are no active input and hfp call
7967 // while closing input stream
7968 if (!adev->active_input && !audio_extn_hfp_is_active(adev))
7969 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307970
Aalique Grahame22e49102018-12-18 14:23:57 -08007971 error_log_destroy(in->error_log);
7972 in->error_log = NULL;
7973
Pallavid7c7a272018-01-16 11:22:55 +05307974 if (in == NULL) {
7975 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
7976 return;
7977 }
7978
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007979 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307980 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007981 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307982 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007983 if (ret != 0)
7984 ALOGE("%s: Compress voip input cannot be closed, error:%d",
7985 __func__, ret);
7986 } else
7987 in_standby(&stream->common);
7988
Revathi Uddarajud2634032017-12-07 14:42:34 +05307989 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07007990 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007991 audio_extn_ssr_deinit();
7992 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007993
Garmond Leunge2433c32017-09-28 21:51:22 -07007994 if (audio_extn_ffv_get_stream() == in) {
7995 audio_extn_ffv_stream_deinit();
7996 }
7997
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307998 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07007999 audio_extn_compr_cap_format_supported(in->config.format))
8000 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05308001
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308002 if (audio_extn_cin_attached_usecase(in->usecase))
8003 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008004
Mingming Yinfd7607b2016-01-22 12:48:44 -08008005 if (in->is_st_session) {
8006 ALOGV("%s: sound trigger pcm stop lab", __func__);
8007 audio_extn_sound_trigger_stop_lab(in);
8008 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008009 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308010 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008011 return;
8012}
8013
Aalique Grahame22e49102018-12-18 14:23:57 -08008014/* verifies input and output devices and their capabilities.
8015 *
8016 * This verification is required when enabling extended bit-depth or
8017 * sampling rates, as not all qcom products support it.
8018 *
8019 * Suitable for calling only on initialization such as adev_open().
8020 * It fills the audio_device use_case_table[] array.
8021 *
8022 * Has a side-effect that it needs to configure audio routing / devices
8023 * in order to power up the devices and read the device parameters.
8024 * It does not acquire any hw device lock. Should restore the devices
8025 * back to "normal state" upon completion.
8026 */
8027static int adev_verify_devices(struct audio_device *adev)
8028{
8029 /* enumeration is a bit difficult because one really wants to pull
8030 * the use_case, device id, etc from the hidden pcm_device_table[].
8031 * In this case there are the following use cases and device ids.
8032 *
8033 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
8034 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
8035 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
8036 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
8037 * [USECASE_AUDIO_RECORD] = {0, 0},
8038 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
8039 * [USECASE_VOICE_CALL] = {2, 2},
8040 *
8041 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
8042 * USECASE_VOICE_CALL omitted, but possible for either input or output.
8043 */
8044
8045 /* should be the usecases enabled in adev_open_input_stream() */
8046 static const int test_in_usecases[] = {
8047 USECASE_AUDIO_RECORD,
8048 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
8049 };
8050 /* should be the usecases enabled in adev_open_output_stream()*/
8051 static const int test_out_usecases[] = {
8052 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
8053 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
8054 };
8055 static const usecase_type_t usecase_type_by_dir[] = {
8056 PCM_PLAYBACK,
8057 PCM_CAPTURE,
8058 };
8059 static const unsigned flags_by_dir[] = {
8060 PCM_OUT,
8061 PCM_IN,
8062 };
8063
8064 size_t i;
8065 unsigned dir;
8066 const unsigned card_id = adev->snd_card;
8067
8068 for (dir = 0; dir < 2; ++dir) {
8069 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
8070 const unsigned flags_dir = flags_by_dir[dir];
8071 const size_t testsize =
8072 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
8073 const int *testcases =
8074 dir ? test_in_usecases : test_out_usecases;
8075 const audio_devices_t audio_device =
8076 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
8077
8078 for (i = 0; i < testsize; ++i) {
8079 const audio_usecase_t audio_usecase = testcases[i];
8080 int device_id;
8081 struct pcm_params **pparams;
8082 struct stream_out out;
8083 struct stream_in in;
8084 struct audio_usecase uc_info;
8085 int retval;
8086
8087 pparams = &adev->use_case_table[audio_usecase];
8088 pcm_params_free(*pparams); /* can accept null input */
8089 *pparams = NULL;
8090
8091 /* find the device ID for the use case (signed, for error) */
8092 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
8093 if (device_id < 0)
8094 continue;
8095
8096 /* prepare structures for device probing */
8097 memset(&uc_info, 0, sizeof(uc_info));
8098 uc_info.id = audio_usecase;
8099 uc_info.type = usecase_type;
8100 if (dir) {
8101 adev->active_input = &in;
8102 memset(&in, 0, sizeof(in));
8103 in.device = audio_device;
8104 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
8105 uc_info.stream.in = &in;
8106 } else {
8107 adev->active_input = NULL;
8108 }
8109 memset(&out, 0, sizeof(out));
8110 out.devices = audio_device; /* only field needed in select_devices */
8111 uc_info.stream.out = &out;
8112 uc_info.devices = audio_device;
8113 uc_info.in_snd_device = SND_DEVICE_NONE;
8114 uc_info.out_snd_device = SND_DEVICE_NONE;
8115 list_add_tail(&adev->usecase_list, &uc_info.list);
8116
8117 /* select device - similar to start_(in/out)put_stream() */
8118 retval = select_devices(adev, audio_usecase);
8119 if (retval >= 0) {
8120 *pparams = pcm_params_get(card_id, device_id, flags_dir);
8121#if LOG_NDEBUG == 0
8122 if (*pparams) {
8123 ALOGV("%s: (%s) card %d device %d", __func__,
8124 dir ? "input" : "output", card_id, device_id);
8125 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
8126 } else {
8127 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
8128 }
8129#endif
8130 }
8131
8132 /* deselect device - similar to stop_(in/out)put_stream() */
8133 /* 1. Get and set stream specific mixer controls */
8134 retval = disable_audio_route(adev, &uc_info);
8135 /* 2. Disable the rx device */
8136 retval = disable_snd_device(adev,
8137 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
8138 list_remove(&uc_info.list);
8139 }
8140 }
8141 adev->active_input = NULL; /* restore adev state */
8142 return 0;
8143}
8144
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308145int adev_create_audio_patch(struct audio_hw_device *dev,
8146 unsigned int num_sources,
8147 const struct audio_port_config *sources,
8148 unsigned int num_sinks,
8149 const struct audio_port_config *sinks,
8150 audio_patch_handle_t *handle)
8151{
8152
8153
8154 return audio_extn_hw_loopback_create_audio_patch(dev,
8155 num_sources,
8156 sources,
8157 num_sinks,
8158 sinks,
8159 handle);
8160
8161}
8162
8163int adev_release_audio_patch(struct audio_hw_device *dev,
8164 audio_patch_handle_t handle)
8165{
8166 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
8167}
8168
8169int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
8170{
8171 return audio_extn_hw_loopback_get_audio_port(dev, config);
8172}
8173
8174int adev_set_audio_port_config(struct audio_hw_device *dev,
8175 const struct audio_port_config *config)
8176{
8177 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
8178}
8179
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008180static int adev_dump(const audio_hw_device_t *device __unused,
8181 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008182{
8183 return 0;
8184}
8185
8186static int adev_close(hw_device_t *device)
8187{
Aalique Grahame22e49102018-12-18 14:23:57 -08008188 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008189 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07008190
8191 if (!adev)
8192 return 0;
8193
8194 pthread_mutex_lock(&adev_init_lock);
8195
8196 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308197 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008198 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08008199 audio_extn_listen_deinit(adev);
Aalique Grahame22e49102018-12-18 14:23:57 -08008200 audio_extn_ma_deinit();
8201 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308202 audio_extn_utils_release_streams_cfg_lists(
8203 &adev->streams_output_cfg_list,
8204 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308205 if (audio_extn_qaf_is_enabled())
8206 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008207 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08008208 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008209 free(adev->snd_dev_ref_cnt);
8210 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08008211 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
8212 pcm_params_free(adev->use_case_table[i]);
8213 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008214 if (adev->adm_deinit)
8215 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308216 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008217 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308218 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308219 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008220 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308221 if (adev->device_cfg_params) {
8222 free(adev->device_cfg_params);
8223 adev->device_cfg_params = NULL;
8224 }
Derek Chend2530072014-11-24 12:39:14 -08008225 if(adev->ext_hw_plugin)
8226 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Kiran Kandi910e1862013-10-29 13:29:42 -07008227 free(device);
8228 adev = NULL;
8229 }
8230 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05308231 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008232 return 0;
8233}
8234
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008235/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
8236 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
8237 * just that it _might_ work.
8238 */
8239static int period_size_is_plausible_for_low_latency(int period_size)
8240{
8241 switch (period_size) {
8242 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07008243 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008244 case 240:
8245 case 320:
8246 case 480:
8247 return 1;
8248 default:
8249 return 0;
8250 }
8251}
8252
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308253static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
8254{
8255 bool is_snd_card_status = false;
8256 bool is_ext_device_status = false;
8257 char value[32];
8258 int card = -1;
8259 card_status_t status;
8260
8261 if (cookie != adev || !parms)
8262 return;
8263
8264 if (!parse_snd_card_status(parms, &card, &status)) {
8265 is_snd_card_status = true;
8266 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
8267 is_ext_device_status = true;
8268 } else {
8269 // not a valid event
8270 return;
8271 }
8272
8273 pthread_mutex_lock(&adev->lock);
8274 if (card == adev->snd_card || is_ext_device_status) {
8275 if (is_snd_card_status && adev->card_status != status) {
8276 adev->card_status = status;
8277 platform_snd_card_update(adev->platform, status);
8278 audio_extn_fm_set_parameters(adev, parms);
8279 } else if (is_ext_device_status) {
8280 platform_set_parameters(adev->platform, parms);
8281 }
8282 }
8283 pthread_mutex_unlock(&adev->lock);
8284 return;
8285}
8286
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308287/* out and adev lock held */
8288static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
8289{
8290 struct audio_usecase *uc_info;
8291 float left_p;
8292 float right_p;
8293 audio_devices_t devices;
8294
8295 uc_info = get_usecase_from_list(adev, out->usecase);
8296 if (uc_info == NULL) {
8297 ALOGE("%s: Could not find the usecase (%d) in the list",
8298 __func__, out->usecase);
8299 return -EINVAL;
8300 }
8301
8302 ALOGD("%s: enter: usecase(%d: %s)", __func__,
8303 out->usecase, use_case_table[out->usecase]);
8304
8305 if (restore) {
8306 // restore A2DP device for active usecases and unmute if required
8307 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
8308 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
8309 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
8310 select_devices(adev, uc_info->id);
8311 pthread_mutex_lock(&out->compr_mute_lock);
8312 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8313 (out->a2dp_compress_mute)) {
8314 out->a2dp_compress_mute = false;
8315 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
8316 }
8317 pthread_mutex_unlock(&out->compr_mute_lock);
8318 }
8319 } else {
8320 // mute compress stream if suspended
8321 pthread_mutex_lock(&out->compr_mute_lock);
8322 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8323 (!out->a2dp_compress_mute)) {
8324 if (!out->standby) {
8325 ALOGD("%s: selecting speaker and muting stream", __func__);
8326 devices = out->devices;
8327 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
8328 left_p = out->volume_l;
8329 right_p = out->volume_r;
8330 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8331 compress_pause(out->compr);
8332 out_set_compr_volume(&out->stream, (float)0, (float)0);
8333 out->a2dp_compress_mute = true;
8334 select_devices(adev, out->usecase);
8335 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8336 compress_resume(out->compr);
8337 out->devices = devices;
8338 out->volume_l = left_p;
8339 out->volume_r = right_p;
8340 }
8341 }
8342 pthread_mutex_unlock(&out->compr_mute_lock);
8343 }
8344 ALOGV("%s: exit", __func__);
8345 return 0;
8346}
8347
8348int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
8349{
8350 int ret = 0;
8351
8352 lock_output_stream(out);
8353 pthread_mutex_lock(&adev->lock);
8354
8355 ret = check_a2dp_restore_l(adev, out, restore);
8356
8357 pthread_mutex_unlock(&adev->lock);
8358 pthread_mutex_unlock(&out->lock);
8359 return ret;
8360}
8361
Haynes Mathew George01156f92018-04-13 15:29:54 -07008362void adev_on_battery_status_changed(bool charging)
8363{
8364 pthread_mutex_lock(&adev->lock);
8365 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
8366 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08008367 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07008368 pthread_mutex_unlock(&adev->lock);
8369}
8370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008371static int adev_open(const hw_module_t *module, const char *name,
8372 hw_device_t **device)
8373{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308374 int ret;
8375
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008376 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008377 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
8378
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008379 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07008380 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008381 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07008382 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008383 ALOGD("%s: returning existing instance of adev", __func__);
8384 ALOGD("%s: exit", __func__);
8385 pthread_mutex_unlock(&adev_init_lock);
8386 return 0;
8387 }
8388
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008389 adev = calloc(1, sizeof(struct audio_device));
8390
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008391 if (!adev) {
8392 pthread_mutex_unlock(&adev_init_lock);
8393 return -ENOMEM;
8394 }
8395
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008396 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
8397
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05308398#ifdef DYNAMIC_LOG_ENABLED
8399 register_for_dynamic_logging("hal");
8400#endif
8401
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008402 adev->device.common.tag = HARDWARE_DEVICE_TAG;
8403 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
8404 adev->device.common.module = (struct hw_module_t *)module;
8405 adev->device.common.close = adev_close;
8406
8407 adev->device.init_check = adev_init_check;
8408 adev->device.set_voice_volume = adev_set_voice_volume;
8409 adev->device.set_master_volume = adev_set_master_volume;
8410 adev->device.get_master_volume = adev_get_master_volume;
8411 adev->device.set_master_mute = adev_set_master_mute;
8412 adev->device.get_master_mute = adev_get_master_mute;
8413 adev->device.set_mode = adev_set_mode;
8414 adev->device.set_mic_mute = adev_set_mic_mute;
8415 adev->device.get_mic_mute = adev_get_mic_mute;
8416 adev->device.set_parameters = adev_set_parameters;
8417 adev->device.get_parameters = adev_get_parameters;
8418 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
8419 adev->device.open_output_stream = adev_open_output_stream;
8420 adev->device.close_output_stream = adev_close_output_stream;
8421 adev->device.open_input_stream = adev_open_input_stream;
8422 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308423 adev->device.create_audio_patch = adev_create_audio_patch;
8424 adev->device.release_audio_patch = adev_release_audio_patch;
8425 adev->device.get_audio_port = adev_get_audio_port;
8426 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008427 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308428 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008429
8430 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008431 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08008432 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008433 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008434 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008435 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08008436 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07008437 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308438 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07008439 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07008440 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008441 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08008442 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08008443 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008444 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05308445 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308446 adev->perf_lock_opts[0] = 0x101;
8447 adev->perf_lock_opts[1] = 0x20E;
8448 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008449 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008451 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07008452 adev->platform = platform_init(adev);
8453 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008454 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008455 free(adev->snd_dev_ref_cnt);
8456 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008457 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07008458 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8459 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08008460 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008461 return -EINVAL;
8462 }
Eric Laurentc4aef752013-09-12 17:45:53 -07008463
Aalique Grahame22e49102018-12-18 14:23:57 -08008464 adev->extspk = audio_extn_extspk_init(adev);
8465
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308466 if (audio_extn_qaf_is_enabled()) {
8467 ret = audio_extn_qaf_init(adev);
8468 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008469 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308470 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008471 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308472 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8473 *device = NULL;
8474 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308475 return ret;
8476 }
8477
8478 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
8479 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
8480 }
8481
Derek Chend2530072014-11-24 12:39:14 -08008482 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
8483
Eric Laurentc4aef752013-09-12 17:45:53 -07008484 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
8485 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
8486 if (adev->visualizer_lib == NULL) {
8487 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
8488 } else {
8489 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
8490 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008491 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008492 "visualizer_hal_start_output");
8493 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008494 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008495 "visualizer_hal_stop_output");
8496 }
8497 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05308498 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08008499 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08008500 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308501 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008502 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07008503
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008504 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
8505 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
8506 if (adev->offload_effects_lib == NULL) {
8507 ALOGE("%s: DLOPEN failed for %s", __func__,
8508 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8509 } else {
8510 ALOGV("%s: DLOPEN successful for %s", __func__,
8511 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8512 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05308513 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008514 "offload_effects_bundle_hal_start_output");
8515 adev->offload_effects_stop_output =
8516 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
8517 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008518 adev->offload_effects_set_hpx_state =
8519 (int (*)(bool))dlsym(adev->offload_effects_lib,
8520 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05308521 adev->offload_effects_get_parameters =
8522 (void (*)(struct str_parms *, struct str_parms *))
8523 dlsym(adev->offload_effects_lib,
8524 "offload_effects_bundle_get_parameters");
8525 adev->offload_effects_set_parameters =
8526 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
8527 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008528 }
8529 }
8530
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008531 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
8532 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
8533 if (adev->adm_lib == NULL) {
8534 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
8535 } else {
8536 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
8537 adev->adm_init = (adm_init_t)
8538 dlsym(adev->adm_lib, "adm_init");
8539 adev->adm_deinit = (adm_deinit_t)
8540 dlsym(adev->adm_lib, "adm_deinit");
8541 adev->adm_register_input_stream = (adm_register_input_stream_t)
8542 dlsym(adev->adm_lib, "adm_register_input_stream");
8543 adev->adm_register_output_stream = (adm_register_output_stream_t)
8544 dlsym(adev->adm_lib, "adm_register_output_stream");
8545 adev->adm_deregister_stream = (adm_deregister_stream_t)
8546 dlsym(adev->adm_lib, "adm_deregister_stream");
8547 adev->adm_request_focus = (adm_request_focus_t)
8548 dlsym(adev->adm_lib, "adm_request_focus");
8549 adev->adm_abandon_focus = (adm_abandon_focus_t)
8550 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008551 adev->adm_set_config = (adm_set_config_t)
8552 dlsym(adev->adm_lib, "adm_set_config");
8553 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
8554 dlsym(adev->adm_lib, "adm_request_focus_v2");
8555 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
8556 dlsym(adev->adm_lib, "adm_is_noirq_avail");
8557 adev->adm_on_routing_change = (adm_on_routing_change_t)
8558 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008559 }
8560 }
8561
Aalique Grahame22e49102018-12-18 14:23:57 -08008562 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07008563 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008564 //initialize this to false for now,
8565 //this will be set to true through set param
8566 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07008567
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07008568 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008569 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08008570
8571 if (k_enable_extended_precision)
8572 adev_verify_devices(adev);
8573
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008574 adev->dsp_bit_width_enforce_mode =
8575 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008576
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308577 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
8578 &adev->streams_output_cfg_list,
8579 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008580
Kiran Kandi910e1862013-10-29 13:29:42 -07008581 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008582
8583 char value[PROPERTY_VALUE_MAX];
8584 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08008585 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
8586 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008587 trial = atoi(value);
8588 if (period_size_is_plausible_for_low_latency(trial)) {
8589 pcm_config_low_latency.period_size = trial;
8590 pcm_config_low_latency.start_threshold = trial / 4;
8591 pcm_config_low_latency.avail_min = trial / 4;
8592 configured_low_latency_capture_period_size = trial;
8593 }
8594 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008595 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
8596 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008597 trial = atoi(value);
8598 if (period_size_is_plausible_for_low_latency(trial)) {
8599 configured_low_latency_capture_period_size = trial;
8600 }
8601 }
8602
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08008603 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
8604
Aalique Grahame22e49102018-12-18 14:23:57 -08008605 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
8606 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008607 af_period_multiplier = atoi(value);
8608 if (af_period_multiplier < 0)
8609 af_period_multiplier = 2;
8610 else if (af_period_multiplier > 4)
8611 af_period_multiplier = 4;
8612
8613 ALOGV("new period_multiplier = %d", af_period_multiplier);
8614 }
8615
Aalique Grahame22e49102018-12-18 14:23:57 -08008616 audio_extn_ma_init(adev->platform);
8617
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008618 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008619 pthread_mutex_unlock(&adev_init_lock);
8620
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008621 if (adev->adm_init)
8622 adev->adm_data = adev->adm_init();
8623
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308624 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308625 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008626 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308627
8628 audio_extn_snd_mon_init();
8629 pthread_mutex_lock(&adev->lock);
8630 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
8631 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07008632 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
8633 /*
8634 * if the battery state callback happens before charging can be queried,
8635 * it will be guarded with the adev->lock held in the cb function and so
8636 * the callback value will reflect the latest state
8637 */
8638 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308639 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08008640 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
8641 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308642 /* Allocate memory for Device config params */
8643 adev->device_cfg_params = (struct audio_device_config_param*)
8644 calloc(platform_get_max_codec_backend(),
8645 sizeof(struct audio_device_config_param));
8646 if (adev->device_cfg_params == NULL)
8647 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308648
Eric Laurent994a6932013-07-17 11:51:42 -07008649 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008650 return 0;
8651}
8652
8653static struct hw_module_methods_t hal_module_methods = {
8654 .open = adev_open,
8655};
8656
8657struct audio_module HAL_MODULE_INFO_SYM = {
8658 .common = {
8659 .tag = HARDWARE_MODULE_TAG,
8660 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
8661 .hal_api_version = HARDWARE_HAL_API_VERSION,
8662 .id = AUDIO_HARDWARE_MODULE_ID,
8663 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08008664 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008665 .methods = &hal_module_methods,
8666 },
8667};