blob: 5959101b54971f6f534dec50308474ab64330af3 [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>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include <audio_effects/effect_aec.h>
69#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053070#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080071#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070072#include "platform_api.h"
73#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070074#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080075#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053076#include "ip_hdlr_intf.h"
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080077#include "audio_feature_manager.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
Arun Mirpuri5d170872019-03-26 13:21:31 -070093#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053094#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053095#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070096
Aalique Grahame22e49102018-12-18 14:23:57 -080097#define RECORD_GAIN_MIN 0.0f
98#define RECORD_GAIN_MAX 1.0f
99#define RECORD_VOLUME_CTL_MAX 0x2000
100
101/* treat as unsigned Q1.13 */
102#define APP_TYPE_GAIN_DEFAULT 0x2000
103
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700104#define PROXY_OPEN_RETRY_COUNT 100
105#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800106
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800107#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
108 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
109 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
110#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
111 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800112
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700113#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700114#define DEFAULT_VOIP_BUF_DURATION_MS 20
115#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
116#define DEFAULT_VOIP_SAMP_RATE 48000
117
118#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
119
120struct pcm_config default_pcm_config_voip_copp = {
121 .channels = 1,
122 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
123 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
124 .period_count = 2,
125 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800126 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
127 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700128};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700129
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700130#define MIN_CHANNEL_COUNT 1
131#define DEFAULT_CHANNEL_COUNT 2
132#define MAX_HIFI_CHANNEL_COUNT 8
133
Aalique Grahame22e49102018-12-18 14:23:57 -0800134#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
135#define MAX_CHANNEL_COUNT 1
136#else
137#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
138#define XSTR(x) STR(x)
139#define STR(x) #x
140#endif
141
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700142static unsigned int configured_low_latency_capture_period_size =
143 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
144
Haynes Mathew George16081042017-05-31 17:16:49 -0700145#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
146#define MMAP_PERIOD_COUNT_MIN 32
147#define MMAP_PERIOD_COUNT_MAX 512
148#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
149
Aalique Grahame22e49102018-12-18 14:23:57 -0800150/* This constant enables extended precision handling.
151 * TODO The flag is off until more testing is done.
152 */
153static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700154extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800155
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
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800178struct pcm_config pcm_config_haptics_audio = {
179 .channels = 1,
180 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
181 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
182 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
183 .format = PCM_FORMAT_S16_LE,
184 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
185 .stop_threshold = INT_MAX,
186 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
187};
188
189struct pcm_config pcm_config_haptics = {
190 .channels = 1,
191 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
192 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
193 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
198};
199
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700200static int af_period_multiplier = 4;
201struct pcm_config pcm_config_rt = {
202 .channels = 2,
203 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
204 .period_size = ULL_PERIOD_SIZE, //1 ms
205 .period_count = 512, //=> buffer size is 512ms
206 .format = PCM_FORMAT_S16_LE,
207 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
208 .stop_threshold = INT_MAX,
209 .silence_threshold = 0,
210 .silence_size = 0,
211 .avail_min = ULL_PERIOD_SIZE, //1 ms
212};
213
Eric Laurentb23d5282013-05-14 15:27:20 -0700214struct pcm_config pcm_config_hdmi_multi = {
215 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
216 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
217 .period_size = HDMI_MULTI_PERIOD_SIZE,
218 .period_count = HDMI_MULTI_PERIOD_COUNT,
219 .format = PCM_FORMAT_S16_LE,
220 .start_threshold = 0,
221 .stop_threshold = INT_MAX,
222 .avail_min = 0,
223};
224
Haynes Mathew George16081042017-05-31 17:16:49 -0700225struct pcm_config pcm_config_mmap_playback = {
226 .channels = 2,
227 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
228 .period_size = MMAP_PERIOD_SIZE,
229 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
230 .format = PCM_FORMAT_S16_LE,
231 .start_threshold = MMAP_PERIOD_SIZE*8,
232 .stop_threshold = INT32_MAX,
233 .silence_threshold = 0,
234 .silence_size = 0,
235 .avail_min = MMAP_PERIOD_SIZE, //1 ms
236};
237
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700238struct pcm_config pcm_config_hifi = {
239 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
240 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
241 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
242 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
243 .format = PCM_FORMAT_S24_3LE,
244 .start_threshold = 0,
245 .stop_threshold = INT_MAX,
246 .avail_min = 0,
247};
248
Eric Laurentb23d5282013-05-14 15:27:20 -0700249struct pcm_config pcm_config_audio_capture = {
250 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700251 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
252 .format = PCM_FORMAT_S16_LE,
253};
254
Haynes Mathew George16081042017-05-31 17:16:49 -0700255struct pcm_config pcm_config_mmap_capture = {
256 .channels = 2,
257 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
258 .period_size = MMAP_PERIOD_SIZE,
259 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
260 .format = PCM_FORMAT_S16_LE,
261 .start_threshold = 0,
262 .stop_threshold = INT_MAX,
263 .silence_threshold = 0,
264 .silence_size = 0,
265 .avail_min = MMAP_PERIOD_SIZE, //1 ms
266};
267
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700268#define AFE_PROXY_CHANNEL_COUNT 2
269#define AFE_PROXY_SAMPLING_RATE 48000
270
271#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
272#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
273
274struct pcm_config pcm_config_afe_proxy_playback = {
275 .channels = AFE_PROXY_CHANNEL_COUNT,
276 .rate = AFE_PROXY_SAMPLING_RATE,
277 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
278 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
279 .format = PCM_FORMAT_S16_LE,
280 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
281 .stop_threshold = INT_MAX,
282 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
283};
284
285#define AFE_PROXY_RECORD_PERIOD_SIZE 768
286#define AFE_PROXY_RECORD_PERIOD_COUNT 4
287
Aalique Grahame22e49102018-12-18 14:23:57 -0800288struct pcm_config pcm_config_audio_capture_rt = {
289 .channels = 2,
290 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
291 .period_size = ULL_PERIOD_SIZE,
292 .period_count = 512,
293 .format = PCM_FORMAT_S16_LE,
294 .start_threshold = 0,
295 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
296 .silence_threshold = 0,
297 .silence_size = 0,
298 .avail_min = ULL_PERIOD_SIZE, //1 ms
299};
300
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700301struct pcm_config pcm_config_afe_proxy_record = {
302 .channels = AFE_PROXY_CHANNEL_COUNT,
303 .rate = AFE_PROXY_SAMPLING_RATE,
304 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
305 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
306 .format = PCM_FORMAT_S16_LE,
307 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
308 .stop_threshold = INT_MAX,
309 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
310};
311
Ashish Jainf1eaa582016-05-23 20:54:24 +0530312#define AUDIO_MAX_PCM_FORMATS 7
313
314const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
315 [AUDIO_FORMAT_DEFAULT] = 0,
316 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
317 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
318 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
319 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
320 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
321 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
322};
323
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800324const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700325 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
326 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800327 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700328 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
329 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700330 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700331 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700332 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
333 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
334 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
335 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
336 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700340 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
341 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700342 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800343 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700344
Eric Laurentb23d5282013-05-14 15:27:20 -0700345 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700346 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530347 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
348 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
349 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530350 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
351 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700352 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700353 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700354 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700355 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700356
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800357 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800358 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700359 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700360
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700361 [USECASE_VOICE2_CALL] = "voice2-call",
362 [USECASE_VOLTE_CALL] = "volte-call",
363 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800364 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800365 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
366 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800367 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700368 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
369 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
370 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800371 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
372 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
373 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
374
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700375 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
376 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700377 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
378 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700379
380 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
381 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530382 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700383
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530384 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530385 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
386 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700387
388 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
389 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530390 /* For Interactive Audio Streams */
391 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
392 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
393 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
394 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
395 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700399
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800400 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
401
402 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback"
Eric Laurentb23d5282013-05-14 15:27:20 -0700403};
404
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700405static const audio_usecase_t offload_usecases[] = {
406 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700407 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
408 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
409 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
410 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
411 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
412 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
413 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
414 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700415};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800416
Varun Balaraje49253e2017-07-06 19:48:56 +0530417static const audio_usecase_t interactive_usecases[] = {
418 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
419 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
420 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
421 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
422 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
423 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
424 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
425 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
426};
427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800428#define STRING_TO_ENUM(string) { #string, string }
429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800430struct string_to_enum {
431 const char *name;
432 uint32_t value;
433};
434
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700435static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800436 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800437 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
438 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
439 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700440 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800441 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
442 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800443 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700444 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
445 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
446 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
447 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
448 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
449 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
450 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
451 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
452 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
453 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
454 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800455};
456
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700457static const struct string_to_enum formats_name_to_enum_table[] = {
458 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
459 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
460 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700461 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
462 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
463 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700464 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800465 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
466 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700467 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800468};
469
470//list of all supported sample rates by HDMI specification.
471static const int out_hdmi_sample_rates[] = {
472 32000, 44100, 48000, 88200, 96000, 176400, 192000,
473};
474
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700475static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800476 STRING_TO_ENUM(32000),
477 STRING_TO_ENUM(44100),
478 STRING_TO_ENUM(48000),
479 STRING_TO_ENUM(88200),
480 STRING_TO_ENUM(96000),
481 STRING_TO_ENUM(176400),
482 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700483};
484
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700485static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700486static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700487static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700488//cache last MBDRC cal step level
489static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700490
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530491static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
492static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700493static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800494static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530495static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530496
Vatsal Buchac09ae062018-11-14 13:25:08 +0530497#ifdef AUDIO_FEATURE_ENABLED_GCOV
498extern void __gcov_flush();
499static void enable_gcov()
500{
501 __gcov_flush();
502}
503#else
504static void enable_gcov()
505{
506}
507#endif
508
justinweng20fb6d82019-02-21 18:49:00 -0700509static int in_set_microphone_direction(const struct audio_stream_in *stream,
510 audio_microphone_direction_t dir);
511static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
512
513
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700514static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
515 int flags __unused)
516{
517 int dir = 0;
518 switch (uc_id) {
519 case USECASE_AUDIO_RECORD_LOW_LATENCY:
520 dir = 1;
521 case USECASE_AUDIO_PLAYBACK_ULL:
522 break;
523 default:
524 return false;
525 }
526
527 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
528 PCM_PLAYBACK : PCM_CAPTURE);
529 if (adev->adm_is_noirq_avail)
530 return adev->adm_is_noirq_avail(adev->adm_data,
531 adev->snd_card, dev_id, dir);
532 return false;
533}
534
535static void register_out_stream(struct stream_out *out)
536{
537 struct audio_device *adev = out->dev;
538 if (is_offload_usecase(out->usecase) ||
539 !adev->adm_register_output_stream)
540 return;
541
542 // register stream first for backward compatibility
543 adev->adm_register_output_stream(adev->adm_data,
544 out->handle,
545 out->flags);
546
547 if (!adev->adm_set_config)
548 return;
549
550 if (out->realtime)
551 adev->adm_set_config(adev->adm_data,
552 out->handle,
553 out->pcm, &out->config);
554}
555
556static void register_in_stream(struct stream_in *in)
557{
558 struct audio_device *adev = in->dev;
559 if (!adev->adm_register_input_stream)
560 return;
561
562 adev->adm_register_input_stream(adev->adm_data,
563 in->capture_handle,
564 in->flags);
565
566 if (!adev->adm_set_config)
567 return;
568
569 if (in->realtime)
570 adev->adm_set_config(adev->adm_data,
571 in->capture_handle,
572 in->pcm,
573 &in->config);
574}
575
576static void request_out_focus(struct stream_out *out, long ns)
577{
578 struct audio_device *adev = out->dev;
579
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700580 if (adev->adm_request_focus_v2)
581 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
582 else if (adev->adm_request_focus)
583 adev->adm_request_focus(adev->adm_data, out->handle);
584}
585
586static void request_in_focus(struct stream_in *in, long ns)
587{
588 struct audio_device *adev = in->dev;
589
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700590 if (adev->adm_request_focus_v2)
591 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
592 else if (adev->adm_request_focus)
593 adev->adm_request_focus(adev->adm_data, in->capture_handle);
594}
595
596static void release_out_focus(struct stream_out *out)
597{
598 struct audio_device *adev = out->dev;
599
600 if (adev->adm_abandon_focus)
601 adev->adm_abandon_focus(adev->adm_data, out->handle);
602}
603
604static void release_in_focus(struct stream_in *in)
605{
606 struct audio_device *adev = in->dev;
607 if (adev->adm_abandon_focus)
608 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
609}
610
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530611static int parse_snd_card_status(struct str_parms *parms, int *card,
612 card_status_t *status)
613{
614 char value[32]={0};
615 char state[32]={0};
616
617 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
618 if (ret < 0)
619 return -1;
620
621 // sscanf should be okay as value is of max length 32.
622 // same as sizeof state.
623 if (sscanf(value, "%d,%s", card, state) < 2)
624 return -1;
625
626 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
627 CARD_STATUS_OFFLINE;
628 return 0;
629}
630
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700631static inline void adjust_frames_for_device_delay(struct stream_out *out,
632 uint32_t *dsp_frames) {
633 // Adjustment accounts for A2dp encoder latency with offload usecases
634 // Note: Encoder latency is returned in ms.
635 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
636 unsigned long offset =
637 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
638 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
639 }
640}
641
vivek mehtaa76401a2015-04-24 14:12:15 -0700642__attribute__ ((visibility ("default")))
643bool audio_hw_send_gain_dep_calibration(int level) {
644 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700645 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700646
647 pthread_mutex_lock(&adev_init_lock);
648
649 if (adev != NULL && adev->platform != NULL) {
650 pthread_mutex_lock(&adev->lock);
651 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700652
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530653 // cache level info for any of the use case which
654 // was not started.
655 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700656
vivek mehtaa76401a2015-04-24 14:12:15 -0700657 pthread_mutex_unlock(&adev->lock);
658 } else {
659 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
660 }
661
662 pthread_mutex_unlock(&adev_init_lock);
663
664 return ret_val;
665}
666
Ashish Jain5106d362016-05-11 19:23:33 +0530667static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
668{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800669 bool gapless_enabled = false;
670 const char *mixer_ctl_name = "Compress Gapless Playback";
671 struct mixer_ctl *ctl;
672
673 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700674 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530675
676 /*Disable gapless if its AV playback*/
677 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800678
679 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
680 if (!ctl) {
681 ALOGE("%s: Could not get ctl for mixer cmd - %s",
682 __func__, mixer_ctl_name);
683 return -EINVAL;
684 }
685
686 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
687 ALOGE("%s: Could not set gapless mode %d",
688 __func__, gapless_enabled);
689 return -EINVAL;
690 }
691 return 0;
692}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700693
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700694__attribute__ ((visibility ("default")))
695int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
696 int table_size) {
697 int ret_val = 0;
698 ALOGV("%s: enter ... ", __func__);
699
700 pthread_mutex_lock(&adev_init_lock);
701 if (adev == NULL) {
702 ALOGW("%s: adev is NULL .... ", __func__);
703 goto done;
704 }
705
706 pthread_mutex_lock(&adev->lock);
707 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
708 pthread_mutex_unlock(&adev->lock);
709done:
710 pthread_mutex_unlock(&adev_init_lock);
711 ALOGV("%s: exit ... ", __func__);
712 return ret_val;
713}
714
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800715bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800716{
717 bool ret = false;
718 ALOGV("%s: enter ...", __func__);
719
720 pthread_mutex_lock(&adev_init_lock);
721
722 if (adev != NULL && adev->platform != NULL) {
723 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800724 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800725 pthread_mutex_unlock(&adev->lock);
726 }
727
728 pthread_mutex_unlock(&adev_init_lock);
729
730 ALOGV("%s: exit with ret %d", __func__, ret);
731 return ret;
732}
Aalique Grahame22e49102018-12-18 14:23:57 -0800733
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700734static bool is_supported_format(audio_format_t format)
735{
Eric Laurent86e17132013-09-12 17:49:30 -0700736 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530737 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530738 format == AUDIO_FORMAT_AAC_LC ||
739 format == AUDIO_FORMAT_AAC_HE_V1 ||
740 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530741 format == AUDIO_FORMAT_AAC_ADTS_LC ||
742 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
743 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530744 format == AUDIO_FORMAT_AAC_LATM_LC ||
745 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
746 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530747 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
748 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530749 format == AUDIO_FORMAT_PCM_FLOAT ||
750 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700751 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530752 format == AUDIO_FORMAT_AC3 ||
753 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700754 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530755 format == AUDIO_FORMAT_DTS ||
756 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800757 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530758 format == AUDIO_FORMAT_ALAC ||
759 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530760 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530761 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800762 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530763 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700764 format == AUDIO_FORMAT_APTX ||
765 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800766 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700767
768 return false;
769}
770
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700771static inline bool is_mmap_usecase(audio_usecase_t uc_id)
772{
773 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
774 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
775}
776
Avinash Vaish71a8b972014-07-24 15:36:33 +0530777static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
778 struct audio_usecase *uc_info)
779{
780 struct listnode *node;
781 struct audio_usecase *usecase;
782
783 if (uc_info == NULL)
784 return -EINVAL;
785
786 /* Re-route all voice usecases on the shared backend other than the
787 specified usecase to new snd devices */
788 list_for_each(node, &adev->usecase_list) {
789 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800790 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530791 enable_audio_route(adev, usecase);
792 }
793 return 0;
794}
795
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530796static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530797{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530798 ALOGV("%s", __func__);
799 audio_route_apply_and_update_path(adev->audio_route,
800 "asrc-mode");
801 adev->asrc_mode_enabled = true;
802}
803
804static void disable_asrc_mode(struct audio_device *adev)
805{
806 ALOGV("%s", __func__);
807 audio_route_reset_and_update_path(adev->audio_route,
808 "asrc-mode");
809 adev->asrc_mode_enabled = false;
810}
811
812/*
813 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
814 * 44.1 or Native DSD backends are enabled for any of current use case.
815 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
816 * - Disable current mix path use case(Headphone backend) and re-enable it with
817 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
818 * e.g. Naitve DSD or Headphone 44.1 -> + 48
819 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530820static void check_and_set_asrc_mode(struct audio_device *adev,
821 struct audio_usecase *uc_info,
822 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530823{
824 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530825 int i, num_new_devices = 0;
826 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
827 /*
828 *Split snd device for new combo use case
829 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
830 */
831 if (platform_split_snd_device(adev->platform,
832 snd_device,
833 &num_new_devices,
834 split_new_snd_devices) == 0) {
835 for (i = 0; i < num_new_devices; i++)
836 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
837 } else {
838 int new_backend_idx = platform_get_backend_index(snd_device);
839 if (((new_backend_idx == HEADPHONE_BACKEND) ||
840 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
841 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
842 !adev->asrc_mode_enabled) {
843 struct listnode *node = NULL;
844 struct audio_usecase *uc = NULL;
845 struct stream_out *curr_out = NULL;
846 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
847 int i, num_devices, ret = 0;
848 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530849
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530850 list_for_each(node, &adev->usecase_list) {
851 uc = node_to_item(node, struct audio_usecase, list);
852 curr_out = (struct stream_out*) uc->stream.out;
853 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
854 /*
855 *Split snd device for existing combo use case
856 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
857 */
858 ret = platform_split_snd_device(adev->platform,
859 uc->out_snd_device,
860 &num_devices,
861 split_snd_devices);
862 if (ret < 0 || num_devices == 0) {
863 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
864 split_snd_devices[0] = uc->out_snd_device;
865 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800866 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530867 for (i = 0; i < num_devices; i++) {
868 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
869 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
870 if((new_backend_idx == HEADPHONE_BACKEND) &&
871 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
872 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
873 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
874 __func__);
875 enable_asrc_mode(adev);
876 break;
877 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
878 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
879 (usecase_backend_idx == HEADPHONE_BACKEND)) {
880 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
881 __func__);
882 disable_audio_route(adev, uc);
883 disable_snd_device(adev, uc->out_snd_device);
884 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
885 if (new_backend_idx == DSD_NATIVE_BACKEND)
886 audio_route_apply_and_update_path(adev->audio_route,
887 "hph-true-highquality-mode");
888 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
889 (curr_out->bit_width >= 24))
890 audio_route_apply_and_update_path(adev->audio_route,
891 "hph-highquality-mode");
892 enable_asrc_mode(adev);
893 enable_snd_device(adev, uc->out_snd_device);
894 enable_audio_route(adev, uc);
895 break;
896 }
897 }
898 // reset split devices count
899 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800900 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530901 if (adev->asrc_mode_enabled)
902 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530903 }
904 }
905 }
906}
907
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700908static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
909 struct audio_effect_config effect_config,
910 unsigned int param_value)
911{
912 char mixer_ctl_name[] = "Audio Effect";
913 struct mixer_ctl *ctl;
914 long set_values[6];
915 struct stream_in *in = adev->active_input;
916
917 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
918 if (!ctl) {
919 ALOGE("%s: Could not get mixer ctl - %s",
920 __func__, mixer_ctl_name);
921 return -EINVAL;
922 }
923
924 set_values[0] = 1; //0:Rx 1:Tx
925 set_values[1] = in->app_type_cfg.app_type;
926 set_values[2] = (long)effect_config.module_id;
927 set_values[3] = (long)effect_config.instance_id;
928 set_values[4] = (long)effect_config.param_id;
929 set_values[5] = param_value;
930
931 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
932
933 return 0;
934
935}
936
937static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
938 int effect_type, unsigned int *param_value)
939{
940 int ret = 0;
941 struct audio_effect_config other_effect_config;
942 struct audio_usecase *usecase = NULL;
943 struct stream_in *in = adev->active_input;
944
945 usecase = get_usecase_from_list(adev, in->usecase);
946 if (!usecase)
947 return -EINVAL;
948
949 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
950 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
951 if (ret < 0) {
952 ALOGE("%s Failed to get effect params %d", __func__, ret);
953 return ret;
954 }
955
956 if (module_id == other_effect_config.module_id) {
957 //Same module id for AEC/NS. Values need to be combined
958 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
959 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
960 *param_value |= other_effect_config.param_value;
961 }
962 }
963
964 return ret;
965}
966
967static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +0530968{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700969 struct audio_effect_config effect_config;
970 struct audio_usecase *usecase = NULL;
971 int ret = 0;
972 unsigned int param_value = 0;
973 struct stream_in *in = adev->active_input;
974
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800975 if(!voice_extn_is_dynamic_ecns_enabled())
976 return ENOSYS;
977
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700978 if (!in) {
979 ALOGE("%s: Invalid input stream", __func__);
980 return -EINVAL;
981 }
982
983 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
984
985 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800986 if (usecase == NULL) {
987 ALOGE("%s: Could not find the usecase (%d) in the list",
988 __func__, in->usecase);
989 return -EINVAL;
990 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700991
992 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
993 if (ret < 0) {
994 ALOGE("%s Failed to get module id %d", __func__, ret);
995 return ret;
996 }
997 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
998 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
999
1000 if(enable)
1001 param_value = effect_config.param_value;
1002
1003 /*Special handling for AEC & NS effects Param values need to be
1004 updated if module ids are same*/
1005
1006 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1007 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1008 if (ret < 0)
1009 return ret;
1010 }
1011
1012 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1013
1014 return ret;
1015}
1016
1017static void check_and_enable_effect(struct audio_device *adev)
1018{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001019 if(!voice_extn_is_dynamic_ecns_enabled())
1020 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001021
1022 if (adev->active_input->enable_aec) {
1023 enable_disable_effect(adev, EFFECT_AEC, true);
1024 }
1025
1026 if (adev->active_input->enable_ns &&
1027 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1028 enable_disable_effect(adev, EFFECT_NS, true);
1029 }
1030}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001031
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001032int pcm_ioctl(struct pcm *pcm, int request, ...)
1033{
1034 va_list ap;
1035 void * arg;
1036 int pcm_fd = *(int*)pcm;
1037
1038 va_start(ap, request);
1039 arg = va_arg(ap, void *);
1040 va_end(ap);
1041
1042 return ioctl(pcm_fd, request, arg);
1043}
1044
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001045int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001046 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001047{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001048 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001049 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301050 struct stream_out *out = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301051 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001052
1053 if (usecase == NULL)
1054 return -EINVAL;
1055
1056 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1057
Surendar Karka93cd25a2018-08-28 14:21:37 +05301058 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001059 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001060 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001061 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001062
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001063#ifdef DS1_DOLBY_DAP_ENABLED
1064 audio_extn_dolby_set_dmid(adev);
1065 audio_extn_dolby_set_endpoint(adev);
1066#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001067 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001068 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301069 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001070 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301071 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301072 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1073 out = usecase->stream.out;
1074 if (out && out->compr)
1075 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1076 }
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301077 audio_extn_set_custom_mtmx_params(adev, usecase, true);
Manish Dewangan58229382017-02-02 15:48:41 +05301078
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001079 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001080 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001081 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301082 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1083 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1084 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1085 if (parms) {
1086 audio_extn_fm_set_parameters(adev, parms);
1087 str_parms_destroy(parms);
1088 }
1089 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001090 ALOGV("%s: exit", __func__);
1091 return 0;
1092}
1093
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001094int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001095 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001096{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001097 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001098 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001099
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301100 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001101 return -EINVAL;
1102
1103 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301104 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001105 snd_device = usecase->in_snd_device;
1106 else
1107 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001108 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001109 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001110 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001111 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001112 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301113 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301114 audio_extn_set_custom_mtmx_params(adev, usecase, false);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301115 if (usecase->stream.out != NULL)
1116 usecase->stream.out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117 ALOGV("%s: exit", __func__);
1118 return 0;
1119}
1120
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001121int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001122 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001123{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301124 int i, num_devices = 0;
1125 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001126 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1127
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001128 if (snd_device < SND_DEVICE_MIN ||
1129 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001130 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001131 return -EINVAL;
1132 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001133
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001134 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001135 ALOGE("%s: Invalid sound device returned", __func__);
1136 return -EINVAL;
1137 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001138
1139 adev->snd_dev_ref_cnt[snd_device]++;
1140
1141 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1142 (platform_split_snd_device(adev->platform,
1143 snd_device,
1144 &num_devices,
1145 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001146 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001147 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001148 return 0;
1149 }
1150
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001151 if (audio_extn_spkr_prot_is_enabled())
1152 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001153
Aalique Grahame22e49102018-12-18 14:23:57 -08001154 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1155
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001156 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1157 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001158 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1159 goto err;
1160 }
1161 audio_extn_dev_arbi_acquire(snd_device);
1162 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001163 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001164 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001165 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001166 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001167 } else if (platform_split_snd_device(adev->platform,
1168 snd_device,
1169 &num_devices,
1170 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301171 for (i = 0; i < num_devices; i++) {
1172 enable_snd_device(adev, new_snd_devices[i]);
1173 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001174 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001175 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001176 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301177
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301178
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001179 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1180 (audio_extn_a2dp_start_playback() < 0)) {
1181 ALOGE(" fail to configure A2dp Source control path ");
1182 goto err;
1183 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001184
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001185 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1186 (audio_extn_a2dp_start_capture() < 0)) {
1187 ALOGE(" fail to configure A2dp Sink control path ");
1188 goto err;
1189 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301190
Zhou Song12c29502019-03-16 10:37:18 +08001191 if (((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1192 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1193 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) &&
1194 (audio_extn_sco_start_configuration() < 0)) {
1195 ALOGE(" fail to configure sco control path ");
1196 goto err;
1197 }
1198
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001199 /* due to the possibility of calibration overwrite between listen
1200 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001201 audio_extn_sound_trigger_update_device_status(snd_device,
1202 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301203 audio_extn_listen_update_device_status(snd_device,
1204 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001205 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001206 audio_extn_sound_trigger_update_device_status(snd_device,
1207 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301208 audio_extn_listen_update_device_status(snd_device,
1209 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001210 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001211 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001212 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001213 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301214
1215 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1216 !adev->native_playback_enabled &&
1217 audio_is_true_native_stream_active(adev)) {
1218 ALOGD("%s: %d: napb: enabling native mode in hardware",
1219 __func__, __LINE__);
1220 audio_route_apply_and_update_path(adev->audio_route,
1221 "true-native-mode");
1222 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301223 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301224 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1225 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001226 (audio_extn_ffv_get_stream() == adev->active_input)) {
1227 ALOGD("%s: init ec ref loopback", __func__);
1228 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1229 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001230 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001231 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001232err:
1233 adev->snd_dev_ref_cnt[snd_device]--;
1234 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001235}
1236
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001237int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001238 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001239{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301240 int i, num_devices = 0;
1241 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001242 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1243
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001244 if (snd_device < SND_DEVICE_MIN ||
1245 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001246 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001247 return -EINVAL;
1248 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001249
1250 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1251 ALOGE("%s: Invalid sound device returned", __func__);
1252 return -EINVAL;
1253 }
1254
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001255 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1256 ALOGE("%s: device ref cnt is already 0", __func__);
1257 return -EINVAL;
1258 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001259
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001260 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001261
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001262
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001263 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001264 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301265
Aalique Grahame22e49102018-12-18 14:23:57 -08001266 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1267
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001268 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1269 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001270 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001271
1272 // when speaker device is disabled, reset swap.
1273 // will be renabled on usecase start
1274 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001275 } else if (platform_split_snd_device(adev->platform,
1276 snd_device,
1277 &num_devices,
1278 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301279 for (i = 0; i < num_devices; i++) {
1280 disable_snd_device(adev, new_snd_devices[i]);
1281 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001282 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001283 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001284 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001285 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001286
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001287 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301288 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001289 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001290 audio_extn_a2dp_stop_capture();
Zhou Song12c29502019-03-16 10:37:18 +08001291 else if ((snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
1292 (snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC) ||
1293 (snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB)) {
1294 if ((adev->snd_dev_ref_cnt[SND_DEVICE_OUT_BT_SCO_SWB] == 0) &&
1295 (adev->snd_dev_ref_cnt[SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC] == 0) &&
1296 (adev->snd_dev_ref_cnt[SND_DEVICE_IN_BT_SCO_MIC_SWB] == 0))
1297 audio_extn_sco_reset_configuration();
1298 } else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001299 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301300 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001301 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301302 adev->native_playback_enabled) {
1303 ALOGD("%s: %d: napb: disabling native mode in hardware",
1304 __func__, __LINE__);
1305 audio_route_reset_and_update_path(adev->audio_route,
1306 "true-native-mode");
1307 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001308 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301309 adev->asrc_mode_enabled) {
1310 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301311 disable_asrc_mode(adev);
1312 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001313 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301314 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001315 (audio_extn_ffv_get_stream() == adev->active_input)) {
1316 ALOGD("%s: deinit ec ref loopback", __func__);
1317 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1318 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001319
1320 audio_extn_utils_release_snd_device(snd_device);
1321 } else {
1322 if (platform_split_snd_device(adev->platform,
1323 snd_device,
1324 &num_devices,
1325 new_snd_devices) == 0) {
1326 for (i = 0; i < num_devices; i++) {
1327 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1328 }
1329 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001330 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001331
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001332 return 0;
1333}
1334
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001335/*
1336 legend:
1337 uc - existing usecase
1338 new_uc - new usecase
1339 d1, d11, d2 - SND_DEVICE enums
1340 a1, a2 - corresponding ANDROID device enums
1341 B1, B2 - backend strings
1342
1343case 1
1344 uc->dev d1 (a1) B1
1345 new_uc->dev d1 (a1), d2 (a2) B1, B2
1346
1347 resolution: disable and enable uc->dev on d1
1348
1349case 2
1350 uc->dev d1 (a1) B1
1351 new_uc->dev d11 (a1) B1
1352
1353 resolution: need to switch uc since d1 and d11 are related
1354 (e.g. speaker and voice-speaker)
1355 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1356
1357case 3
1358 uc->dev d1 (a1) B1
1359 new_uc->dev d2 (a2) B2
1360
1361 resolution: no need to switch uc
1362
1363case 4
1364 uc->dev d1 (a1) B1
1365 new_uc->dev d2 (a2) B1
1366
1367 resolution: disable enable uc-dev on d2 since backends match
1368 we cannot enable two streams on two different devices if they
1369 share the same backend. e.g. if offload is on speaker device using
1370 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1371 using the same backend, offload must also be switched to voice-handset.
1372
1373case 5
1374 uc->dev d1 (a1) B1
1375 new_uc->dev d1 (a1), d2 (a2) B1
1376
1377 resolution: disable enable uc-dev on d2 since backends match
1378 we cannot enable two streams on two different devices if they
1379 share the same backend.
1380
1381case 6
1382 uc->dev d1 (a1) B1
1383 new_uc->dev d2 (a1) B2
1384
1385 resolution: no need to switch
1386
1387case 7
1388 uc->dev d1 (a1), d2 (a2) B1, B2
1389 new_uc->dev d1 (a1) B1
1390
1391 resolution: no need to switch
1392
Zhou Song4ba65882018-07-09 14:48:07 +08001393case 8
1394 uc->dev d1 (a1) B1
1395 new_uc->dev d11 (a1), d2 (a2) B1, B2
1396 resolution: compared to case 1, for this case, d1 and d11 are related
1397 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001398*/
1399static snd_device_t derive_playback_snd_device(void * platform,
1400 struct audio_usecase *uc,
1401 struct audio_usecase *new_uc,
1402 snd_device_t new_snd_device)
1403{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301404 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001405
1406 snd_device_t d1 = uc->out_snd_device;
1407 snd_device_t d2 = new_snd_device;
1408
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301409 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301410 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301411 a1 = uc->stream.inout->out_config.devices;
1412 a2 = new_uc->stream.inout->out_config.devices;
1413 break;
1414 default :
1415 a1 = uc->stream.out->devices;
1416 a2 = new_uc->stream.out->devices;
1417 break;
1418 }
1419
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001420 // Treat as a special case when a1 and a2 are not disjoint
1421 if ((a1 != a2) && (a1 & a2)) {
1422 snd_device_t d3[2];
1423 int num_devices = 0;
1424 int ret = platform_split_snd_device(platform,
1425 popcount(a1) > 1 ? d1 : d2,
1426 &num_devices,
1427 d3);
1428 if (ret < 0) {
1429 if (ret != -ENOSYS) {
1430 ALOGW("%s failed to split snd_device %d",
1431 __func__,
1432 popcount(a1) > 1 ? d1 : d2);
1433 }
1434 goto end;
1435 }
1436
1437 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1438 // But if it does happen, we need to give priority to d2 if
1439 // the combo devices active on the existing usecase share a backend.
1440 // This is because we cannot have a usecase active on a combo device
1441 // and a new usecase requests one device in this combo pair.
1442 if (platform_check_backends_match(d3[0], d3[1])) {
1443 return d2; // case 5
1444 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001445 // check if d1 is related to any of d3's
1446 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001447 return d1; // case 1
1448 else
1449 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001450 }
1451 } else {
1452 if (platform_check_backends_match(d1, d2)) {
1453 return d2; // case 2, 4
1454 } else {
1455 return d1; // case 6, 3
1456 }
1457 }
1458
1459end:
1460 return d2; // return whatever was calculated before.
1461}
1462
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001463static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301464 struct audio_usecase *uc_info,
1465 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001466{
1467 struct listnode *node;
1468 struct audio_usecase *usecase;
1469 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301470 snd_device_t uc_derive_snd_device;
1471 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001472 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1473 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001474 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301475 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001476 /*
1477 * This function is to make sure that all the usecases that are active on
1478 * the hardware codec backend are always routed to any one device that is
1479 * handled by the hardware codec.
1480 * For example, if low-latency and deep-buffer usecases are currently active
1481 * on speaker and out_set_parameters(headset) is received on low-latency
1482 * output, then we have to make sure deep-buffer is also switched to headset,
1483 * because of the limitation that both the devices cannot be enabled
1484 * at the same time as they share the same backend.
1485 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001486 /*
1487 * This call is to check if we need to force routing for a particular stream
1488 * If there is a backend configuration change for the device when a
1489 * new stream starts, then ADM needs to be closed and re-opened with the new
1490 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001491 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001492 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001493 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1494 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301495 /* For a2dp device reconfigure all active sessions
1496 * with new AFE encoder format based on a2dp state
1497 */
1498 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1499 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1500 audio_extn_a2dp_is_force_device_switch()) {
1501 force_routing = true;
1502 force_restart_session = true;
1503 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301504 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1505
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001506 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001507 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001508 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001509 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1510 switch_device[i] = false;
1511
1512 list_for_each(node, &adev->usecase_list) {
1513 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001514
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301515 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1516 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301517 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301518 platform_get_snd_device_name(usecase->out_snd_device),
1519 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301520 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1521 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1522 usecase, uc_info, snd_device);
1523 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1524 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1525 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1526 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001527 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301528 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1529 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1530 ((force_restart_session) ||
1531 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301532 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1533 __func__, use_case_table[usecase->id],
1534 platform_get_snd_device_name(usecase->out_snd_device));
1535 disable_audio_route(adev, usecase);
1536 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301537 /* Enable existing usecase on derived playback device */
1538 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301539 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301540 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001541 }
1542 }
1543
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301544 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1545 num_uc_to_switch);
1546
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001547 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001548 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001549
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301550 /* Make sure the previous devices to be disabled first and then enable the
1551 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001552 list_for_each(node, &adev->usecase_list) {
1553 usecase = node_to_item(node, struct audio_usecase, list);
1554 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001555 /* Check if output sound device to be switched can be split and if any
1556 of the split devices match with derived sound device */
1557 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1558 &num_devices, split_snd_devices) == 0) {
1559 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1560 for (i = 0; i < num_devices; i++) {
1561 /* Disable devices that do not match with derived sound device */
1562 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1563 disable_snd_device(adev, split_snd_devices[i]);
1564 }
1565 } else {
1566 disable_snd_device(adev, usecase->out_snd_device);
1567 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001568 }
1569 }
1570
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001571 list_for_each(node, &adev->usecase_list) {
1572 usecase = node_to_item(node, struct audio_usecase, list);
1573 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001574 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1575 &num_devices, split_snd_devices) == 0) {
1576 /* Enable derived sound device only if it does not match with
1577 one of the split sound devices. This is because the matching
1578 sound device was not disabled */
1579 bool should_enable = true;
1580 for (i = 0; i < num_devices; i++) {
1581 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1582 should_enable = false;
1583 break;
1584 }
1585 }
1586 if (should_enable)
1587 enable_snd_device(adev, derive_snd_device[usecase->id]);
1588 } else {
1589 enable_snd_device(adev, derive_snd_device[usecase->id]);
1590 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001591 }
1592 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001593
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001594 /* Re-route all the usecases on the shared backend other than the
1595 specified usecase to new snd devices */
1596 list_for_each(node, &adev->usecase_list) {
1597 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301598 /* Update the out_snd_device only before enabling the audio route */
1599 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301600 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301601 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301602 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301603 use_case_table[usecase->id],
1604 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001605 /* Update voc calibration before enabling VoIP route */
1606 if (usecase->type == VOIP_CALL)
1607 status = platform_switch_voice_call_device_post(adev->platform,
1608 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001609 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301610 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001611 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1612 out_set_voip_volume(&usecase->stream.out->stream,
1613 usecase->stream.out->volume_l,
1614 usecase->stream.out->volume_r);
1615 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301616 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001617 }
1618 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001619 }
1620}
1621
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301622static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001623 struct audio_usecase *uc_info,
1624 snd_device_t snd_device)
1625{
1626 struct listnode *node;
1627 struct audio_usecase *usecase;
1628 bool switch_device[AUDIO_USECASE_MAX];
1629 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301630 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001631 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001632
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301633 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1634 snd_device);
1635 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301636
1637 /*
1638 * Make sure out devices is checked against out codec backend device and
1639 * also in devices against in codec backend. Checking out device against in
1640 * codec backend or vice versa causes issues.
1641 */
1642 if (uc_info->type == PCM_CAPTURE)
1643 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001644 /*
1645 * This function is to make sure that all the active capture usecases
1646 * are always routed to the same input sound device.
1647 * For example, if audio-record and voice-call usecases are currently
1648 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1649 * is received for voice call then we have to make sure that audio-record
1650 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1651 * because of the limitation that two devices cannot be enabled
1652 * at the same time if they share the same backend.
1653 */
1654 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1655 switch_device[i] = false;
1656
1657 list_for_each(node, &adev->usecase_list) {
1658 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301659 /*
1660 * TODO: Enhance below condition to handle BT sco/USB multi recording
1661 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001662 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001663 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301664 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301665 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301666 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301667 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001668 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001669 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1670 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001671 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001672 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001673 switch_device[usecase->id] = true;
1674 num_uc_to_switch++;
1675 }
1676 }
1677
1678 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001679 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001680
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301681 /* Make sure the previous devices to be disabled first and then enable the
1682 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001683 list_for_each(node, &adev->usecase_list) {
1684 usecase = node_to_item(node, struct audio_usecase, list);
1685 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001686 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001687 }
1688 }
1689
1690 list_for_each(node, &adev->usecase_list) {
1691 usecase = node_to_item(node, struct audio_usecase, list);
1692 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001693 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001694 }
1695 }
1696
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001697 /* Re-route all the usecases on the shared backend other than the
1698 specified usecase to new snd devices */
1699 list_for_each(node, &adev->usecase_list) {
1700 usecase = node_to_item(node, struct audio_usecase, list);
1701 /* Update the in_snd_device only before enabling the audio route */
1702 if (switch_device[usecase->id] ) {
1703 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001704 if (usecase->type != VOICE_CALL) {
1705 /* Update voc calibration before enabling VoIP route */
1706 if (usecase->type == VOIP_CALL)
1707 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001708 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001709 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301710 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001711 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001712 }
1713 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001714 }
1715}
1716
Mingming Yin3a941d42016-02-17 18:08:05 -08001717static void reset_hdmi_sink_caps(struct stream_out *out) {
1718 int i = 0;
1719
1720 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1721 out->supported_channel_masks[i] = 0;
1722 }
1723 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1724 out->supported_formats[i] = 0;
1725 }
1726 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1727 out->supported_sample_rates[i] = 0;
1728 }
1729}
1730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001732static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001733{
Mingming Yin3a941d42016-02-17 18:08:05 -08001734 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001735 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001736
Mingming Yin3a941d42016-02-17 18:08:05 -08001737 reset_hdmi_sink_caps(out);
1738
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001739 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001740 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001741 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001742 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001743 }
1744
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001746 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001747 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001748 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001749 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1750 case 6:
1751 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1752 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1753 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1754 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1755 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1756 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001757 break;
1758 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001759 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001760 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001761 break;
1762 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001763
1764 // check channel format caps
1765 i = 0;
1766 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1767 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1768 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1769 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1770 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1771 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1772 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1773 }
1774
Ben Romberger1aaaf862017-04-06 17:49:46 -07001775 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1776 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1777 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1778 }
1779
Mingming Yin3a941d42016-02-17 18:08:05 -08001780 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1781 ALOGV(":%s HDMI supports DTS format", __func__);
1782 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1783 }
1784
1785 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1786 ALOGV(":%s HDMI supports DTS HD format", __func__);
1787 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1788 }
1789
Naresh Tanniru928f0862017-04-07 16:44:23 -07001790 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1791 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1792 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1793 }
1794
Mingming Yin3a941d42016-02-17 18:08:05 -08001795
1796 // check sample rate caps
1797 i = 0;
1798 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1799 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1800 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1801 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1802 }
1803 }
1804
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001805 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806}
1807
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001808static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1809 uint32_t *supported_sample_rates __unused,
1810 uint32_t max_rates __unused)
1811{
1812 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1813 supported_sample_rates,
1814 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301815 ssize_t i = 0;
1816
1817 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001818 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1819 supported_sample_rates[i]);
1820 }
1821 return count;
1822}
1823
1824static inline int read_usb_sup_channel_masks(bool is_playback,
1825 audio_channel_mask_t *supported_channel_masks,
1826 uint32_t max_masks)
1827{
1828 int channels = audio_extn_usb_get_max_channels(is_playback);
1829 int channel_count;
1830 uint32_t num_masks = 0;
1831 if (channels > MAX_HIFI_CHANNEL_COUNT)
1832 channels = MAX_HIFI_CHANNEL_COUNT;
1833
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301834 channel_count = DEFAULT_CHANNEL_COUNT;
1835
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001836 if (is_playback) {
1837 // For playback we never report mono because the framework always outputs stereo
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001838 // audio_channel_out_mask_from_count() does return positional masks for channel counts
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301839 // above 2 but we want indexed masks here.
1840 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001841 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001842 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1843 // indexed mask
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301844 supported_channel_masks[num_masks++] = audio_channel_in_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001845 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301846
1847 for (channel_count = channels; ((channel_count >= DEFAULT_CHANNEL_COUNT) &&
1848 (num_masks < max_masks)); channel_count--) {
1849 supported_channel_masks[num_masks++] =
1850 audio_channel_mask_for_index_assignment_from_count(channel_count);
1851 }
1852
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001853 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1854 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1855 return num_masks;
1856}
1857
1858static inline int read_usb_sup_formats(bool is_playback __unused,
1859 audio_format_t *supported_formats,
1860 uint32_t max_formats __unused)
1861{
1862 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1863 switch (bitwidth) {
1864 case 24:
1865 // XXX : usb.c returns 24 for s24 and s24_le?
1866 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1867 break;
1868 case 32:
1869 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1870 break;
1871 case 16:
1872 default :
1873 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1874 break;
1875 }
1876 ALOGV("%s: %s supported format %d", __func__,
1877 is_playback ? "P" : "C", bitwidth);
1878 return 1;
1879}
1880
1881static inline int read_usb_sup_params_and_compare(bool is_playback,
1882 audio_format_t *format,
1883 audio_format_t *supported_formats,
1884 uint32_t max_formats,
1885 audio_channel_mask_t *mask,
1886 audio_channel_mask_t *supported_channel_masks,
1887 uint32_t max_masks,
1888 uint32_t *rate,
1889 uint32_t *supported_sample_rates,
1890 uint32_t max_rates) {
1891 int ret = 0;
1892 int num_formats;
1893 int num_masks;
1894 int num_rates;
1895 int i;
1896
1897 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1898 max_formats);
1899 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1900 max_masks);
1901
1902 num_rates = read_usb_sup_sample_rates(is_playback,
1903 supported_sample_rates, max_rates);
1904
1905#define LUT(table, len, what, dflt) \
1906 for (i=0; i<len && (table[i] != what); i++); \
1907 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1908
1909 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1910 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1911 LUT(supported_sample_rates, num_rates, *rate, 0);
1912
1913#undef LUT
1914 return ret < 0 ? -EINVAL : 0; // HACK TBD
1915}
1916
Alexy Josephb1379942016-01-29 15:49:38 -08001917audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001918 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001919{
1920 struct audio_usecase *usecase;
1921 struct listnode *node;
1922
1923 list_for_each(node, &adev->usecase_list) {
1924 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001925 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001926 ALOGV("%s: usecase id %d", __func__, usecase->id);
1927 return usecase->id;
1928 }
1929 }
1930 return USECASE_INVALID;
1931}
1932
Alexy Josephb1379942016-01-29 15:49:38 -08001933struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001934 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001935{
1936 struct audio_usecase *usecase;
1937 struct listnode *node;
1938
1939 list_for_each(node, &adev->usecase_list) {
1940 usecase = node_to_item(node, struct audio_usecase, list);
1941 if (usecase->id == uc_id)
1942 return usecase;
1943 }
1944 return NULL;
1945}
1946
Dhananjay Kumard4833242016-10-06 22:09:12 +05301947struct stream_in *get_next_active_input(const struct audio_device *adev)
1948{
1949 struct audio_usecase *usecase;
1950 struct listnode *node;
1951
1952 list_for_each_reverse(node, &adev->usecase_list) {
1953 usecase = node_to_item(node, struct audio_usecase, list);
1954 if (usecase->type == PCM_CAPTURE)
1955 return usecase->stream.in;
1956 }
1957 return NULL;
1958}
1959
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301960/*
1961 * is a true native playback active
1962 */
1963bool audio_is_true_native_stream_active(struct audio_device *adev)
1964{
1965 bool active = false;
1966 int i = 0;
1967 struct listnode *node;
1968
1969 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1970 ALOGV("%s:napb: not in true mode or non hdphones device",
1971 __func__);
1972 active = false;
1973 goto exit;
1974 }
1975
1976 list_for_each(node, &adev->usecase_list) {
1977 struct audio_usecase *uc;
1978 uc = node_to_item(node, struct audio_usecase, list);
1979 struct stream_out *curr_out =
1980 (struct stream_out*) uc->stream.out;
1981
1982 if (curr_out && PCM_PLAYBACK == uc->type) {
1983 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1984 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1985 uc->id, curr_out->sample_rate,
1986 curr_out->bit_width,
1987 platform_get_snd_device_name(uc->out_snd_device));
1988
1989 if (is_offload_usecase(uc->id) &&
1990 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1991 active = true;
1992 ALOGD("%s:napb:native stream detected", __func__);
1993 }
1994 }
1995 }
1996exit:
1997 return active;
1998}
1999
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002000uint32_t adev_get_dsp_bit_width_enforce_mode()
2001{
2002 if (adev == NULL) {
2003 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2004 return 0;
2005 }
2006 return adev->dsp_bit_width_enforce_mode;
2007}
2008
2009static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2010{
2011 char value[PROPERTY_VALUE_MAX];
2012 int trial;
2013 uint32_t dsp_bit_width_enforce_mode = 0;
2014
2015 if (!mixer) {
2016 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2017 __func__);
2018 return 0;
2019 }
2020
2021 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2022 value, NULL) > 0) {
2023 trial = atoi(value);
2024 switch (trial) {
2025 case 16:
2026 dsp_bit_width_enforce_mode = 16;
2027 break;
2028 case 24:
2029 dsp_bit_width_enforce_mode = 24;
2030 break;
2031 case 32:
2032 dsp_bit_width_enforce_mode = 32;
2033 break;
2034 default:
2035 dsp_bit_width_enforce_mode = 0;
2036 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2037 break;
2038 }
2039 }
2040
2041 return dsp_bit_width_enforce_mode;
2042}
2043
2044static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2045 uint32_t enforce_mode,
2046 bool enable)
2047{
2048 struct mixer_ctl *ctl = NULL;
2049 const char *mixer_ctl_name = "ASM Bit Width";
2050 uint32_t asm_bit_width_mode = 0;
2051
2052 if (enforce_mode == 0) {
2053 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2054 return;
2055 }
2056
2057 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2058 if (!ctl) {
2059 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2060 __func__, mixer_ctl_name);
2061 return;
2062 }
2063
2064 if (enable)
2065 asm_bit_width_mode = enforce_mode;
2066 else
2067 asm_bit_width_mode = 0;
2068
2069 ALOGV("%s DSP bit width feature status is %d width=%d",
2070 __func__, enable, asm_bit_width_mode);
2071 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2072 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2073 asm_bit_width_mode);
2074
2075 return;
2076}
2077
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302078/*
2079 * if native DSD playback active
2080 */
2081bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2082{
2083 bool active = false;
2084 struct listnode *node = NULL;
2085 struct audio_usecase *uc = NULL;
2086 struct stream_out *curr_out = NULL;
2087
2088 list_for_each(node, &adev->usecase_list) {
2089 uc = node_to_item(node, struct audio_usecase, list);
2090 curr_out = (struct stream_out*) uc->stream.out;
2091
2092 if (curr_out && PCM_PLAYBACK == uc->type &&
2093 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2094 active = true;
2095 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302096 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302097 }
2098 }
2099 return active;
2100}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302101
2102static bool force_device_switch(struct audio_usecase *usecase)
2103{
2104 bool ret = false;
2105 bool is_it_true_mode = false;
2106
Zhou Song30f2c3e2018-02-08 14:02:15 +08002107 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302108 usecase->type == TRANSCODE_LOOPBACK_RX ||
2109 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002110 return false;
2111 }
2112
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002113 if(usecase->stream.out == NULL) {
2114 ALOGE("%s: stream.out is NULL", __func__);
2115 return false;
2116 }
2117
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302118 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002119 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2120 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2121 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302122 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2123 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2124 (!is_it_true_mode && adev->native_playback_enabled)){
2125 ret = true;
2126 ALOGD("napb: time to toggle native mode");
2127 }
2128 }
2129
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302130 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302131 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2132 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002133 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302134 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302135 ALOGD("Force a2dp device switch to update new encoder config");
2136 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002137 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302138
Florian Pfister1a84f312018-07-19 14:38:18 +02002139 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302140 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2141 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002142 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302143 return ret;
2144}
2145
Aalique Grahame22e49102018-12-18 14:23:57 -08002146static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2147{
2148 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2149}
2150
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302151bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2152{
2153 bool ret=false;
2154 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2155 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2156 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2157 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2158 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2159 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2160 ret = true;
2161
2162 return ret;
2163}
2164
2165bool is_a2dp_device(snd_device_t out_snd_device)
2166{
2167 bool ret=false;
2168 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2169 ret = true;
2170
2171 return ret;
2172}
2173
2174bool is_bt_soc_on(struct audio_device *adev)
2175{
2176 struct mixer_ctl *ctl;
2177 char *mixer_ctl_name = "BT SOC status";
2178 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2179 bool bt_soc_status = true;
2180 if (!ctl) {
2181 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2182 __func__, mixer_ctl_name);
2183 /*This is to ensure we dont break targets which dont have the kernel change*/
2184 return true;
2185 }
2186 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2187 ALOGD("BT SOC status: %d",bt_soc_status);
2188 return bt_soc_status;
2189}
2190
2191int out_standby_l(struct audio_stream *stream);
2192
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002193int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002195 snd_device_t out_snd_device = SND_DEVICE_NONE;
2196 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002197 struct audio_usecase *usecase = NULL;
2198 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002199 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002200 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302201 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002202 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002203 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002204
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302205 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2206
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002207 usecase = get_usecase_from_list(adev, uc_id);
2208 if (usecase == NULL) {
2209 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2210 return -EINVAL;
2211 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002213 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002214 (usecase->type == VOIP_CALL) ||
2215 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302216 if(usecase->stream.out == NULL) {
2217 ALOGE("%s: stream.out is NULL", __func__);
2218 return -EINVAL;
2219 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002220 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002221 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002222 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002223 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302224 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302225 if (usecase->stream.inout == NULL) {
2226 ALOGE("%s: stream.inout is NULL", __func__);
2227 return -EINVAL;
2228 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302229 stream_out.devices = usecase->stream.inout->out_config.devices;
2230 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2231 stream_out.format = usecase->stream.inout->out_config.format;
2232 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2233 out_snd_device = platform_get_output_snd_device(adev->platform,
2234 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302235 usecase->devices = out_snd_device;
2236 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2237 if (usecase->stream.inout == NULL) {
2238 ALOGE("%s: stream.inout is NULL", __func__);
2239 return -EINVAL;
2240 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302241 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302242 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002243 } else {
2244 /*
2245 * If the voice call is active, use the sound devices of voice call usecase
2246 * so that it would not result any device switch. All the usecases will
2247 * be switched to new device when select_devices() is called for voice call
2248 * usecase. This is to avoid switching devices for voice call when
2249 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002250 * choose voice call device only if the use case device is
2251 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002252 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002253 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002254 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002255 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002256 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2257 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302258 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2259 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002260 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002261 in_snd_device = vc_usecase->in_snd_device;
2262 out_snd_device = vc_usecase->out_snd_device;
2263 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002264 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002265 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002266 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002267 if ((voip_usecase != NULL) &&
2268 (usecase->type == PCM_PLAYBACK) &&
2269 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002270 out_snd_device_backend_match = platform_check_backends_match(
2271 voip_usecase->out_snd_device,
2272 platform_get_output_snd_device(
2273 adev->platform,
2274 usecase->stream.out));
2275 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002276 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002277 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2278 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002279 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002280 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002281 in_snd_device = voip_usecase->in_snd_device;
2282 out_snd_device = voip_usecase->out_snd_device;
2283 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002284 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002285 hfp_ucid = audio_extn_hfp_get_usecase();
2286 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002287 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002288 in_snd_device = hfp_usecase->in_snd_device;
2289 out_snd_device = hfp_usecase->out_snd_device;
2290 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002291 }
2292 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302293 if (usecase->stream.out == NULL) {
2294 ALOGE("%s: stream.out is NULL", __func__);
2295 return -EINVAL;
2296 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002297 usecase->devices = usecase->stream.out->devices;
2298 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002299 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002300 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002301 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002302 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizb27e7952018-10-12 15:49:35 +08002303 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002304 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2305
2306 if ((usecase->stream.out != NULL &&
2307 voip_usecase != NULL &&
2308 usecase->stream.out->usecase == voip_usecase->id) &&
2309 adev->active_input &&
Aalique Grahame22e49102018-12-18 14:23:57 -08002310 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2311 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
kunleizdcf967a2018-08-07 17:09:11 +08002312 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002313 select_devices(adev, adev->active_input->usecase);
2314 }
2315 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002316 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302317 if (usecase->stream.in == NULL) {
2318 ALOGE("%s: stream.in is NULL", __func__);
2319 return -EINVAL;
2320 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002321 usecase->devices = usecase->stream.in->device;
2322 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002323 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002324 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002325 if (adev->active_input &&
2326 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302327 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002328 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2329 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2330 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2331 out_device = voip_usecase->stream.out->devices;
2332 else if (adev->primary_output && !adev->primary_output->standby)
2333 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002334 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002335 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2336 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002337 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002338 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002339 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002340 }
2341 }
2342
2343 if (out_snd_device == usecase->out_snd_device &&
2344 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302345
2346 if (!force_device_switch(usecase))
2347 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002348 }
2349
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302350 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002351 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302352 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2353 return 0;
2354 }
2355
Aalique Grahame22e49102018-12-18 14:23:57 -08002356 if (out_snd_device != SND_DEVICE_NONE &&
2357 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2358 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2359 __func__,
2360 use_case_table[uc_id],
2361 adev->last_logged_snd_device[uc_id][0],
2362 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2363 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2364 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2365 -1,
2366 out_snd_device,
2367 platform_get_snd_device_name(out_snd_device),
2368 platform_get_snd_device_acdb_id(out_snd_device));
2369 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2370 }
2371 if (in_snd_device != SND_DEVICE_NONE &&
2372 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2373 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2374 __func__,
2375 use_case_table[uc_id],
2376 adev->last_logged_snd_device[uc_id][1],
2377 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2378 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2379 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2380 -1,
2381 in_snd_device,
2382 platform_get_snd_device_name(in_snd_device),
2383 platform_get_snd_device_acdb_id(in_snd_device));
2384 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2385 }
2386
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002387
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388 /*
2389 * Limitation: While in call, to do a device switch we need to disable
2390 * and enable both RX and TX devices though one of them is same as current
2391 * device.
2392 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002393 if ((usecase->type == VOICE_CALL) &&
2394 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2395 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002396 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002397 }
2398
2399 if (((usecase->type == VOICE_CALL) ||
2400 (usecase->type == VOIP_CALL)) &&
2401 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2402 /* Disable sidetone only if voice/voip call already exists */
2403 if (voice_is_call_state_active(adev) ||
2404 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002405 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002406
2407 /* Disable aanc only if voice call exists */
2408 if (voice_is_call_state_active(adev))
2409 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002410 }
2411
Aalique Grahame22e49102018-12-18 14:23:57 -08002412 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2413 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002414 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302415 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002416 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2417 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2418 else
2419 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302420 }
2421
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002422 /* Disable current sound devices */
2423 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002424 disable_audio_route(adev, usecase);
2425 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426 }
2427
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002428 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002429 disable_audio_route(adev, usecase);
2430 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002431 }
2432
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002433 /* Applicable only on the targets that has external modem.
2434 * New device information should be sent to modem before enabling
2435 * the devices to reduce in-call device switch time.
2436 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002437 if ((usecase->type == VOICE_CALL) &&
2438 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2439 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002440 status = platform_switch_voice_call_enable_device_config(adev->platform,
2441 out_snd_device,
2442 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002443 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002444
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002445 /* Enable new sound devices */
2446 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002447 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302448 if (platform_check_codec_asrc_support(adev->platform))
2449 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002450 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451 }
2452
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002453 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302454 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002455 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002456 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002457
Avinash Vaish71a8b972014-07-24 15:36:33 +05302458 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002459 status = platform_switch_voice_call_device_post(adev->platform,
2460 out_snd_device,
2461 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302462 enable_audio_route_for_voice_usecases(adev, usecase);
2463 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002464
sangwoo170731f2013-06-08 15:36:36 +09002465 usecase->in_snd_device = in_snd_device;
2466 usecase->out_snd_device = out_snd_device;
2467
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302468 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2469 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302470 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002471 if ((24 == usecase->stream.out->bit_width) &&
2472 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2473 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2474 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2475 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2476 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2477 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2478 /*
2479 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2480 * configured device sample rate, if not update the COPP rate to be equal to the
2481 * device sample rate, else open COPP at stream sample rate
2482 */
2483 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2484 usecase->stream.out->sample_rate,
2485 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302486 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2487 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002488 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2489 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2490 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2491 }
2492
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08002493 /* Notify device change info to effect clients registered */
2494 audio_extn_gef_notify_device_config(
2495 usecase->stream.out->devices,
2496 usecase->stream.out->channel_mask,
2497 usecase->stream.out->app_type_cfg.sample_rate,
2498 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302499 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002500 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002501
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002502 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002503
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002504 /* If input stream is already running then effect needs to be
2505 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002506 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2507 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002508 check_and_enable_effect(adev);
2509
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002510 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002511 /* Enable aanc only if voice call exists */
2512 if (voice_is_call_state_active(adev))
2513 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2514
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002515 /* Enable sidetone only if other voice/voip call already exists */
2516 if (voice_is_call_state_active(adev) ||
2517 voice_extn_compress_voip_is_started(adev))
2518 voice_set_sidetone(adev, out_snd_device, true);
2519 }
2520
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002521 /* Applicable only on the targets that has external modem.
2522 * Enable device command should be sent to modem only after
2523 * enabling voice call mixer controls
2524 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002525 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002526 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2527 out_snd_device,
2528 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302529
2530 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2531
2532 if (usecase->type == VOIP_CALL) {
2533 if (adev->active_input != NULL &&
2534 !adev->active_input->standby) {
2535 if (is_bt_soc_on(adev) == false){
2536 ALOGD("BT SCO MIC disconnected while in connection");
2537 if (adev->active_input->pcm != NULL)
2538 pcm_stop(adev->active_input->pcm);
2539 }
2540 }
2541 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2542 && usecase->stream.out->started) {
2543 if (is_bt_soc_on(adev) == false) {
2544 ALOGD("BT SCO/A2DP disconnected while in connection");
2545 out_standby_l(&usecase->stream.out->stream.common);
2546 }
2547 }
2548 } else if ((usecase->stream.out != NULL) &&
2549 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302550 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2551 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302552 usecase->stream.out->started) {
2553 if (is_bt_soc_on(adev) == false) {
2554 ALOGD("BT SCO/A2dp disconnected while in connection");
2555 out_standby_l(&usecase->stream.out->stream.common);
2556 }
2557 }
2558 }
2559
Aalique Grahame22e49102018-12-18 14:23:57 -08002560 if (usecase == voip_usecase) {
2561 struct stream_out *voip_out = voip_usecase->stream.out;
2562 audio_extn_utils_send_app_type_gain(adev,
2563 voip_out->app_type_cfg.app_type,
2564 &voip_out->app_type_cfg.gain[0]);
2565 }
2566
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302567 ALOGD("%s: done",__func__);
2568
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569 return status;
2570}
2571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002572static int stop_input_stream(struct stream_in *in)
2573{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302574 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302576
2577 if (in == NULL) {
2578 ALOGE("%s: stream_in ptr is NULL", __func__);
2579 return -EINVAL;
2580 }
2581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 struct audio_device *adev = in->dev;
2583
Eric Laurent994a6932013-07-17 11:51:42 -07002584 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002585 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586 uc_info = get_usecase_from_list(adev, in->usecase);
2587 if (uc_info == NULL) {
2588 ALOGE("%s: Could not find the usecase (%d) in the list",
2589 __func__, in->usecase);
2590 return -EINVAL;
2591 }
2592
Derek Chenea197282019-01-07 17:35:01 -08002593 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2594 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002595
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002596 /* Close in-call recording streams */
2597 voice_check_and_stop_incall_rec_usecase(adev, in);
2598
Eric Laurent150dbfe2013-02-27 14:31:02 -08002599 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002600 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002601
2602 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002603 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002605 list_remove(&uc_info->list);
2606 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002608 adev->active_input = get_next_active_input(adev);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302609 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002610 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 return ret;
2612}
2613
2614int start_input_stream(struct stream_in *in)
2615{
2616 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002617 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302619
2620 if (in == NULL) {
2621 ALOGE("%s: stream_in ptr is NULL", __func__);
2622 return -EINVAL;
2623 }
2624
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002625 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002626 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002627 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628
Mingming Yin2664a5b2015-09-03 10:53:11 -07002629 if (get_usecase_from_list(adev, usecase) == NULL)
2630 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302631 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2632 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002633
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302634 if (CARD_STATUS_OFFLINE == in->card_status||
2635 CARD_STATUS_OFFLINE == adev->card_status) {
2636 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302637 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302638 goto error_config;
2639 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302640
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302641 if (audio_is_bluetooth_sco_device(in->device)) {
2642 if (!adev->bt_sco_on) {
2643 ALOGE("%s: SCO profile is not ready, return error", __func__);
2644 ret = -EIO;
2645 goto error_config;
2646 }
2647 }
2648
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002649 /* Check if source matches incall recording usecase criteria */
2650 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2651 if (ret)
2652 goto error_config;
2653 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002654 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2655
2656 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2657 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2658 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002659 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002660 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002661
Eric Laurentb23d5282013-05-14 15:27:20 -07002662 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663 if (in->pcm_device_id < 0) {
2664 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2665 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002666 ret = -EINVAL;
2667 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002669
2670 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002672
2673 if (!uc_info) {
2674 ret = -ENOMEM;
2675 goto error_config;
2676 }
2677
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002678 uc_info->id = in->usecase;
2679 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002680 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002681 uc_info->devices = in->device;
2682 uc_info->in_snd_device = SND_DEVICE_NONE;
2683 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002685 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302686 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2687 adev->perf_lock_opts,
2688 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002689 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690
Derek Chenea197282019-01-07 17:35:01 -08002691 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2692 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002693
Haynes Mathew George16081042017-05-31 17:16:49 -07002694 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302695 ret = audio_extn_cin_start_input_stream(in);
2696 if (ret)
2697 goto error_open;
2698 else
2699 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002700 }
2701
Haynes Mathew George16081042017-05-31 17:16:49 -07002702 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002703 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002704 ALOGE("%s: pcm stream not ready", __func__);
2705 goto error_open;
2706 }
2707 ret = pcm_start(in->pcm);
2708 if (ret < 0) {
2709 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2710 goto error_open;
2711 }
2712 } else {
2713 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2714 unsigned int pcm_open_retry_count = 0;
2715
2716 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2717 flags |= PCM_MMAP | PCM_NOIRQ;
2718 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2719 } else if (in->realtime) {
2720 flags |= PCM_MMAP | PCM_NOIRQ;
2721 }
2722
Garmond Leunge2433c32017-09-28 21:51:22 -07002723 if (audio_extn_ffv_get_stream() == in) {
2724 ALOGD("%s: ffv stream, update pcm config", __func__);
2725 audio_extn_ffv_update_pcm_config(&config);
2726 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002727 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2728 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2729
2730 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002731 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002732 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002733 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002734 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302735 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302736 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2737 adev->card_status = CARD_STATUS_OFFLINE;
2738 in->card_status = CARD_STATUS_OFFLINE;
2739 ret = -EIO;
2740 goto error_open;
2741 }
2742
Haynes Mathew George16081042017-05-31 17:16:49 -07002743 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2744 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2745 if (in->pcm != NULL) {
2746 pcm_close(in->pcm);
2747 in->pcm = NULL;
2748 }
2749 if (pcm_open_retry_count-- == 0) {
2750 ret = -EIO;
2751 goto error_open;
2752 }
2753 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2754 continue;
2755 }
2756 break;
2757 }
2758
2759 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002760 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002761 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002762 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002763 if (ret < 0) {
2764 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2765 pcm_close(in->pcm);
2766 in->pcm = NULL;
2767 goto error_open;
2768 }
2769 register_in_stream(in);
2770 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002771 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002772 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002773 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002774 if (ret < 0) {
2775 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002776 pcm_close(in->pcm);
2777 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002778 goto error_open;
2779 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002780 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002781 }
2782
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002783 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07002784 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
2785 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002786
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302787done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302788 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002789 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302790 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002791 return ret;
2792
2793error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302794 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002796error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302797 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302798 /*
2799 * sleep 50ms to allow sufficient time for kernel
2800 * drivers to recover incases like SSR.
2801 */
2802 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002803 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302804 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002805 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806}
2807
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002808void lock_input_stream(struct stream_in *in)
2809{
2810 pthread_mutex_lock(&in->pre_lock);
2811 pthread_mutex_lock(&in->lock);
2812 pthread_mutex_unlock(&in->pre_lock);
2813}
2814
2815void lock_output_stream(struct stream_out *out)
2816{
2817 pthread_mutex_lock(&out->pre_lock);
2818 pthread_mutex_lock(&out->lock);
2819 pthread_mutex_unlock(&out->pre_lock);
2820}
2821
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002822/* must be called with out->lock locked */
2823static int send_offload_cmd_l(struct stream_out* out, int command)
2824{
2825 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2826
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002827 if (!cmd) {
2828 ALOGE("failed to allocate mem for command 0x%x", command);
2829 return -ENOMEM;
2830 }
2831
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002832 ALOGVV("%s %d", __func__, command);
2833
2834 cmd->cmd = command;
2835 list_add_tail(&out->offload_cmd_list, &cmd->node);
2836 pthread_cond_signal(&out->offload_cond);
2837 return 0;
2838}
2839
2840/* must be called iwth out->lock locked */
2841static void stop_compressed_output_l(struct stream_out *out)
2842{
2843 out->offload_state = OFFLOAD_STATE_IDLE;
2844 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002845 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002846 if (out->compr != NULL) {
2847 compress_stop(out->compr);
2848 while (out->offload_thread_blocked) {
2849 pthread_cond_wait(&out->cond, &out->lock);
2850 }
2851 }
2852}
2853
Varun Balaraje49253e2017-07-06 19:48:56 +05302854bool is_interactive_usecase(audio_usecase_t uc_id)
2855{
2856 unsigned int i;
2857 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2858 if (uc_id == interactive_usecases[i])
2859 return true;
2860 }
2861 return false;
2862}
2863
2864static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2865{
2866 audio_usecase_t ret_uc = USECASE_INVALID;
2867 unsigned int intract_uc_index;
2868 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2869
2870 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2871 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2872 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2873 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2874 ret_uc = interactive_usecases[intract_uc_index];
2875 break;
2876 }
2877 }
2878
2879 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2880 return ret_uc;
2881}
2882
2883static void free_interactive_usecase(struct audio_device *adev,
2884 audio_usecase_t uc_id)
2885{
2886 unsigned int interact_uc_index;
2887 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2888
2889 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2890 if (interactive_usecases[interact_uc_index] == uc_id) {
2891 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2892 break;
2893 }
2894 }
2895 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2896}
2897
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002898bool is_offload_usecase(audio_usecase_t uc_id)
2899{
2900 unsigned int i;
2901 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2902 if (uc_id == offload_usecases[i])
2903 return true;
2904 }
2905 return false;
2906}
2907
Dhananjay Kumarac341582017-02-23 23:42:25 +05302908static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002909{
vivek mehta446c3962015-09-14 10:57:35 -07002910 audio_usecase_t ret_uc = USECASE_INVALID;
2911 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002912 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002913 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302914 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002915 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2916 else
2917 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002918
vivek mehta446c3962015-09-14 10:57:35 -07002919 pthread_mutex_lock(&adev->lock);
2920 if (get_usecase_from_list(adev, ret_uc) != NULL)
2921 ret_uc = USECASE_INVALID;
2922 pthread_mutex_unlock(&adev->lock);
2923
2924 return ret_uc;
2925 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002926
2927 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002928 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2929 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2930 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2931 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002932 break;
2933 }
2934 }
vivek mehta446c3962015-09-14 10:57:35 -07002935
2936 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2937 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002938}
2939
2940static void free_offload_usecase(struct audio_device *adev,
2941 audio_usecase_t uc_id)
2942{
vivek mehta446c3962015-09-14 10:57:35 -07002943 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002944 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002945
2946 if (!adev->multi_offload_enable)
2947 return;
2948
2949 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2950 if (offload_usecases[offload_uc_index] == uc_id) {
2951 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002952 break;
2953 }
2954 }
2955 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2956}
2957
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002958static void *offload_thread_loop(void *context)
2959{
2960 struct stream_out *out = (struct stream_out *) context;
2961 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002962 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002963
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002964 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002965 //set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002966 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2967
2968 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002969 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002970 for (;;) {
2971 struct offload_cmd *cmd = NULL;
2972 stream_callback_event_t event;
2973 bool send_callback = false;
2974
2975 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2976 __func__, list_empty(&out->offload_cmd_list),
2977 out->offload_state);
2978 if (list_empty(&out->offload_cmd_list)) {
2979 ALOGV("%s SLEEPING", __func__);
2980 pthread_cond_wait(&out->offload_cond, &out->lock);
2981 ALOGV("%s RUNNING", __func__);
2982 continue;
2983 }
2984
2985 item = list_head(&out->offload_cmd_list);
2986 cmd = node_to_item(item, struct offload_cmd, node);
2987 list_remove(item);
2988
2989 ALOGVV("%s STATE %d CMD %d out->compr %p",
2990 __func__, out->offload_state, cmd->cmd, out->compr);
2991
2992 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2993 free(cmd);
2994 break;
2995 }
2996
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002997 // allow OFFLOAD_CMD_ERROR reporting during standby
2998 // this is needed to handle failures during compress_open
2999 // Note however that on a pause timeout, the stream is closed
3000 // and no offload usecase will be active. Therefore this
3001 // special case is needed for compress_open failures alone
3002 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3003 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003004 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003005 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003006 pthread_cond_signal(&out->cond);
3007 continue;
3008 }
3009 out->offload_thread_blocked = true;
3010 pthread_mutex_unlock(&out->lock);
3011 send_callback = false;
3012 switch(cmd->cmd) {
3013 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003014 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003015 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003016 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003017 send_callback = true;
3018 event = STREAM_CBK_EVENT_WRITE_READY;
3019 break;
3020 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003021 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303022 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003023 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303024 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003025 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303026 if (ret < 0)
3027 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303028 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303029 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003030 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003031 else
3032 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003033 if (-ENETRESET != ret && !(-EINTR == ret &&
3034 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303035 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303036 pthread_mutex_lock(&out->lock);
3037 out->send_new_metadata = 1;
3038 out->send_next_track_params = true;
3039 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303040 event = STREAM_CBK_EVENT_DRAIN_READY;
3041 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3042 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303043 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003044 break;
3045 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003046 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003047 ret = compress_drain(out->compr);
3048 ALOGD("copl(%p):out of compress_drain", out);
3049 // EINTR check avoids drain interruption due to SSR
3050 if (-ENETRESET != ret && !(-EINTR == ret &&
3051 CARD_STATUS_OFFLINE == out->card_status)) {
3052 send_callback = true;
3053 event = STREAM_CBK_EVENT_DRAIN_READY;
3054 } else
3055 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003056 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303057 case OFFLOAD_CMD_ERROR:
3058 ALOGD("copl(%p): sending error callback to AF", out);
3059 send_callback = true;
3060 event = STREAM_CBK_EVENT_ERROR;
3061 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003062 default:
3063 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3064 break;
3065 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003066 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003067 out->offload_thread_blocked = false;
3068 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003069 if (send_callback && out->client_callback) {
3070 ALOGVV("%s: sending client_callback event %d", __func__, event);
3071 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003072 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073 free(cmd);
3074 }
3075
3076 pthread_cond_signal(&out->cond);
3077 while (!list_empty(&out->offload_cmd_list)) {
3078 item = list_head(&out->offload_cmd_list);
3079 list_remove(item);
3080 free(node_to_item(item, struct offload_cmd, node));
3081 }
3082 pthread_mutex_unlock(&out->lock);
3083
3084 return NULL;
3085}
3086
3087static int create_offload_callback_thread(struct stream_out *out)
3088{
3089 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3090 list_init(&out->offload_cmd_list);
3091 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3092 offload_thread_loop, out);
3093 return 0;
3094}
3095
3096static int destroy_offload_callback_thread(struct stream_out *out)
3097{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003098 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003099 stop_compressed_output_l(out);
3100 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3101
3102 pthread_mutex_unlock(&out->lock);
3103 pthread_join(out->offload_thread, (void **) NULL);
3104 pthread_cond_destroy(&out->offload_cond);
3105
3106 return 0;
3107}
3108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109static int stop_output_stream(struct stream_out *out)
3110{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303111 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003112 struct audio_usecase *uc_info;
3113 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003114 bool has_voip_usecase =
3115 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116
Eric Laurent994a6932013-07-17 11:51:42 -07003117 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003118 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119 uc_info = get_usecase_from_list(adev, out->usecase);
3120 if (uc_info == NULL) {
3121 ALOGE("%s: Could not find the usecase (%d) in the list",
3122 __func__, out->usecase);
3123 return -EINVAL;
3124 }
3125
Derek Chenea197282019-01-07 17:35:01 -08003126 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3127 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003128
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003129 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303130 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003131 if (adev->visualizer_stop_output != NULL)
3132 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003133
3134 audio_extn_dts_remove_state_notifier_node(out->usecase);
3135
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003136 if (adev->offload_effects_stop_output != NULL)
3137 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
3138 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003139
Arun Mirpurief53ce52018-09-11 18:00:09 -07003140 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3141 voice_set_device_mute_flag(adev, false);
3142
Eric Laurent150dbfe2013-02-27 14:31:02 -08003143 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003144 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003145
3146 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003147 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148
Aalique Grahame22e49102018-12-18 14:23:57 -08003149 audio_extn_extspk_update(adev->extspk);
3150
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003151 if (is_offload_usecase(out->usecase)) {
3152 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3153 adev->dsp_bit_width_enforce_mode,
3154 false);
3155 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003156 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3157 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3158 false);
3159
3160 if (ret != 0)
3161 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3162 /* default service interval was successfully updated,
3163 reopen USB backend with new service interval */
3164 ret = 0;
3165 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003166
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003167 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303168 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003169 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303170 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003171 ALOGV("Disable passthrough , reset mixer to pcm");
3172 /* NO_PASSTHROUGH */
3173 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003174 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003175 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3176 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003177
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303178 /* Must be called after removing the usecase from list */
3179 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303180 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303181
Manish Dewangan21a850a2017-08-14 12:03:55 +05303182 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003183 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3184 if (ret < 0)
3185 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3186 }
3187
Aalique Grahame22e49102018-12-18 14:23:57 -08003188 if (has_voip_usecase ||
3189 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3190 struct listnode *node;
3191 struct audio_usecase *usecase;
3192 list_for_each(node, &adev->usecase_list) {
3193 usecase = node_to_item(node, struct audio_usecase, list);
3194 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
3195 continue;
3196
3197 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3198 __func__, usecase->id, use_case_table[usecase->id],
3199 out->usecase, use_case_table[out->usecase]);
3200 select_devices(adev, usecase->id);
3201 }
3202 }
3203
Garmond Leung5fd0b552018-04-17 11:56:12 -07003204 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003205 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206 return ret;
3207}
3208
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003209struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3210 unsigned int flags, unsigned int pcm_open_retry_count,
3211 struct pcm_config *config)
3212{
3213 struct pcm* pcm = NULL;
3214
3215 while (1) {
3216 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3217 if (pcm == NULL || !pcm_is_ready(pcm)) {
3218 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3219 if (pcm != NULL) {
3220 pcm_close(pcm);
3221 pcm = NULL;
3222 }
3223 if (pcm_open_retry_count-- == 0)
3224 return NULL;
3225
3226 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3227 continue;
3228 }
3229 break;
3230 }
3231
3232 if (pcm_is_ready(pcm)) {
3233 int ret = pcm_prepare(pcm);
3234 if (ret < 0) {
3235 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3236 pcm_close(pcm);
3237 pcm = NULL;
3238 }
3239 }
3240
3241 return pcm;
3242}
3243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244int start_output_stream(struct stream_out *out)
3245{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003246 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247 struct audio_usecase *uc_info;
3248 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003249 char mixer_ctl_name[128];
3250 struct mixer_ctl *ctl = NULL;
3251 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303252 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003253 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254
Haynes Mathew George380745d2017-10-04 15:27:45 -07003255 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003256 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3257 ret = -EINVAL;
3258 goto error_config;
3259 }
3260
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003261 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303262 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003263 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303264
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303265 if (CARD_STATUS_OFFLINE == out->card_status ||
3266 CARD_STATUS_OFFLINE == adev->card_status) {
3267 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303268 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303269 goto error_config;
3270 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303271
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303272 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003273 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003274 if (out->devices &
3275 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303276 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303277 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303278 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3279 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3280 ret = -EAGAIN;
3281 goto error_config;
3282 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303283 }
3284 }
3285 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303286 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3287 if (!adev->bt_sco_on) {
3288 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3289 //combo usecase just by pass a2dp
3290 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3291 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3292 } else {
3293 ALOGE("%s: SCO profile is not ready, return error", __func__);
3294 ret = -EAGAIN;
3295 goto error_config;
3296 }
3297 }
3298 }
3299
Eric Laurentb23d5282013-05-14 15:27:20 -07003300 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003301 if (out->pcm_device_id < 0) {
3302 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3303 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003304 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003305 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306 }
3307
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003308 if (is_haptic_usecase) {
3309 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3310 if (adev->haptic_pcm_device_id < 0) {
3311 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3312 __func__, adev->haptic_pcm_device_id, out->usecase);
3313 ret = -EINVAL;
3314 goto error_config;
3315 }
3316 }
3317
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003319
3320 if (!uc_info) {
3321 ret = -ENOMEM;
3322 goto error_config;
3323 }
3324
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325 uc_info->id = out->usecase;
3326 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003327 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003328 uc_info->devices = out->devices;
3329 uc_info->in_snd_device = SND_DEVICE_NONE;
3330 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003331
3332 /* This must be called before adding this usecase to the list */
3333 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3334 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3335 /* USB backend is not reopened immediately.
3336 This is eventually done as part of select_devices */
3337 }
3338
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003339 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303341 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3342 adev->perf_lock_opts,
3343 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303344
3345 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303346 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303347 if (audio_extn_passthru_is_enabled() &&
3348 audio_extn_passthru_is_passthrough_stream(out)) {
3349 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303350 }
3351 }
3352
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303353 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003354 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303355 if (!a2dp_combo) {
3356 check_a2dp_restore_l(adev, out, false);
3357 } else {
3358 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003359 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3360 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3361 else
3362 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303363 select_devices(adev, out->usecase);
3364 out->devices = dev;
3365 }
3366 } else {
3367 select_devices(adev, out->usecase);
3368 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003369
Arun Mirpurief53ce52018-09-11 18:00:09 -07003370 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3371 voice_set_device_mute_flag(adev, true);
3372
Derek Chenea197282019-01-07 17:35:01 -08003373 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3374 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003375
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003376 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3377 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003378
3379 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003380 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003381 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3382 ALOGE("%s: pcm stream not ready", __func__);
3383 goto error_open;
3384 }
3385 ret = pcm_start(out->pcm);
3386 if (ret < 0) {
3387 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3388 goto error_open;
3389 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003390 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003391 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003392 unsigned int flags = PCM_OUT;
3393 unsigned int pcm_open_retry_count = 0;
3394 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3395 flags |= PCM_MMAP | PCM_NOIRQ;
3396 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003397 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003398 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003399 } else
3400 flags |= PCM_MONOTONIC;
3401
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003402 if ((adev->vr_audio_mode_enabled) &&
3403 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3404 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3405 "PCM_Dev %d Topology", out->pcm_device_id);
3406 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3407 if (!ctl) {
3408 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3409 __func__, mixer_ctl_name);
3410 } else {
3411 //if success use ULLPP
3412 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3413 __func__, mixer_ctl_name, out->pcm_device_id);
3414 //There is a still a possibility that some sessions
3415 // that request for FAST|RAW when 3D audio is active
3416 //can go through ULLPP. Ideally we expects apps to
3417 //listen to audio focus and stop concurrent playback
3418 //Also, we will look for mode flag (voice_in_communication)
3419 //before enabling the realtime flag.
3420 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3421 }
3422 }
3423
Surendar Karka91fa3682018-07-02 18:12:12 +05303424 if (out->realtime)
3425 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3426 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3427
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003428 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3429 flags, pcm_open_retry_count,
3430 &(out->config));
3431 if (out->pcm == NULL) {
3432 ret = -EIO;
3433 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003434 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003435
3436 if (is_haptic_usecase) {
3437 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3438 adev->haptic_pcm_device_id,
3439 flags, pcm_open_retry_count,
3440 &(adev->haptics_config));
3441 // failure to open haptics pcm shouldnt stop audio,
3442 // so do not close audio pcm in case of error
3443 }
3444
Surendar Karka91fa3682018-07-02 18:12:12 +05303445 if (!out->realtime)
3446 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303447 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003448
Zhou Song2b8f28f2017-09-11 10:51:38 +08003449 // apply volume for voip playback after path is set up
3450 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3451 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303452 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3453 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303454 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3455 out->apply_volume = false;
3456 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003457 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003458 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303459 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003460 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3461 adev->dsp_bit_width_enforce_mode,
3462 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003464 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003465 out->compr = compress_open(adev->snd_card,
3466 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003467 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003468 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303469 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303470 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3471 adev->card_status = CARD_STATUS_OFFLINE;
3472 out->card_status = CARD_STATUS_OFFLINE;
3473 ret = -EIO;
3474 goto error_open;
3475 }
3476
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003477 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003478 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003479 compress_close(out->compr);
3480 out->compr = NULL;
3481 ret = -EIO;
3482 goto error_open;
3483 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303484 /* compress_open sends params of the track, so reset the flag here */
3485 out->is_compr_metadata_avail = false;
3486
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003487 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003488 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003489
Fred Oh3f43e742015-03-04 18:42:34 -08003490 /* Since small bufs uses blocking writes, a write will be blocked
3491 for the default max poll time (20s) in the event of an SSR.
3492 Reduce the poll time to observe and deal with SSR faster.
3493 */
Ashish Jain5106d362016-05-11 19:23:33 +05303494 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003495 compress_set_max_poll_wait(out->compr, 1000);
3496 }
3497
Manish Dewangan69426c82017-01-30 17:35:36 +05303498 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303499 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303500
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003501 audio_extn_dts_create_state_notifier_node(out->usecase);
3502 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3503 popcount(out->channel_mask),
3504 out->playback_started);
3505
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003506#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303507 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003508 audio_extn_dolby_send_ddp_endp_params(adev);
3509#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303510 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3511 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003512 if (adev->visualizer_start_output != NULL)
3513 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3514 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303515 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003516 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003517 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003519
3520 if (ret == 0) {
3521 register_out_stream(out);
3522 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003523 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3524 ALOGE("%s: pcm stream not ready", __func__);
3525 goto error_open;
3526 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003527 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003528 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003529 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003530 if (ret < 0)
3531 goto error_open;
3532 }
3533 }
3534
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303535 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003536 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003537
Manish Dewangan21a850a2017-08-14 12:03:55 +05303538 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003539 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003540 if (ret < 0)
3541 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3542 }
3543
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003544 // consider a scenario where on pause lower layers are tear down.
3545 // so on resume, swap mixer control need to be sent only when
3546 // backend is active, hence rather than sending from enable device
3547 // sending it from start of streamtream
3548
3549 platform_set_swap_channels(adev, true);
3550
Haynes Mathew George380745d2017-10-04 15:27:45 -07003551 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303552 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003553 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003554error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003555 if (adev->haptic_pcm) {
3556 pcm_close(adev->haptic_pcm);
3557 adev->haptic_pcm = NULL;
3558 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303559 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003561error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303562 /*
3563 * sleep 50ms to allow sufficient time for kernel
3564 * drivers to recover incases like SSR.
3565 */
3566 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003567 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303568 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003569 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570}
3571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572static int check_input_parameters(uint32_t sample_rate,
3573 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003574 int channel_count,
3575 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003577 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303579 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3580 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3581 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003582 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003583 !audio_extn_compr_cap_format_supported(format) &&
3584 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003585 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003586
Aalique Grahame22e49102018-12-18 14:23:57 -08003587 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3588 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3589 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3590 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3591 return -EINVAL;
3592 }
3593
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003594 switch (channel_count) {
3595 case 1:
3596 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303597 case 3:
3598 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003599 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003600 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003601 break;
3602 default:
3603 ret = -EINVAL;
3604 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003605
3606 switch (sample_rate) {
3607 case 8000:
3608 case 11025:
3609 case 12000:
3610 case 16000:
3611 case 22050:
3612 case 24000:
3613 case 32000:
3614 case 44100:
3615 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003616 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303617 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003618 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303619 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620 break;
3621 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003622 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623 }
3624
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003625 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626}
3627
Naresh Tanniru04f71882018-06-26 17:46:22 +05303628
3629/** Add a value in a list if not already present.
3630 * @return true if value was successfully inserted or already present,
3631 * false if the list is full and does not contain the value.
3632 */
3633static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3634 for (size_t i = 0; i < list_length; i++) {
3635 if (list[i] == value) return true; // value is already present
3636 if (list[i] == 0) { // no values in this slot
3637 list[i] = value;
3638 return true; // value inserted
3639 }
3640 }
3641 return false; // could not insert value
3642}
3643
3644/** Add channel_mask in supported_channel_masks if not already present.
3645 * @return true if channel_mask was successfully inserted or already present,
3646 * false if supported_channel_masks is full and does not contain channel_mask.
3647 */
3648static void register_channel_mask(audio_channel_mask_t channel_mask,
3649 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3650 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3651 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3652}
3653
3654/** Add format in supported_formats if not already present.
3655 * @return true if format was successfully inserted or already present,
3656 * false if supported_formats is full and does not contain format.
3657 */
3658static void register_format(audio_format_t format,
3659 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3660 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3661 "%s: stream can not declare supporting its format %x", __func__, format);
3662}
3663/** Add sample_rate in supported_sample_rates if not already present.
3664 * @return true if sample_rate was successfully inserted or already present,
3665 * false if supported_sample_rates is full and does not contain sample_rate.
3666 */
3667static void register_sample_rate(uint32_t sample_rate,
3668 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3669 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3670 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3671}
3672
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003673static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3674{
3675 uint32_t high = num1, low = num2, temp = 0;
3676
3677 if (!num1 || !num2)
3678 return 0;
3679
3680 if (num1 < num2) {
3681 high = num2;
3682 low = num1;
3683 }
3684
3685 while (low != 0) {
3686 temp = low;
3687 low = high % low;
3688 high = temp;
3689 }
3690 return (num1 * num2)/high;
3691}
3692
3693static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3694{
3695 uint32_t remainder = 0;
3696
3697 if (!multiplier)
3698 return num;
3699
3700 remainder = num % multiplier;
3701 if (remainder)
3702 num += (multiplier - remainder);
3703
3704 return num;
3705}
3706
Aalique Grahame22e49102018-12-18 14:23:57 -08003707static size_t get_stream_buffer_size(size_t duration_ms,
3708 uint32_t sample_rate,
3709 audio_format_t format,
3710 int channel_count,
3711 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712{
3713 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003714 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715
Aalique Grahame22e49102018-12-18 14:23:57 -08003716 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003717 if (is_low_latency)
3718 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303719
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003720 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08003721 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003722
Ralf Herzbd08d632018-09-28 15:50:49 +02003723 /* make sure the size is multiple of 32 bytes and additionally multiple of
3724 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003725 * At 48 kHz mono 16-bit PCM:
3726 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3727 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003728 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003729 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003730 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003731
3732 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733}
3734
Aalique Grahame22e49102018-12-18 14:23:57 -08003735static size_t get_input_buffer_size(uint32_t sample_rate,
3736 audio_format_t format,
3737 int channel_count,
3738 bool is_low_latency)
3739{
3740 /* Don't know if USB HIFI in this context so use true to be conservative */
3741 if (check_input_parameters(sample_rate, format, channel_count,
3742 true /*is_usb_hifi */) != 0)
3743 return 0;
3744
3745 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
3746 sample_rate,
3747 format,
3748 channel_count,
3749 is_low_latency);
3750}
3751
Ashish Jain058165c2016-09-28 23:18:48 +05303752static size_t get_output_period_size(uint32_t sample_rate,
3753 audio_format_t format,
3754 int channel_count,
3755 int duration /*in millisecs*/)
3756{
3757 size_t size = 0;
3758 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3759
3760 if ((duration == 0) || (sample_rate == 0) ||
3761 (bytes_per_sample == 0) || (channel_count == 0)) {
3762 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3763 bytes_per_sample, channel_count);
3764 return -EINVAL;
3765 }
3766
3767 size = (sample_rate *
3768 duration *
3769 bytes_per_sample *
3770 channel_count) / 1000;
3771 /*
3772 * To have same PCM samples for all channels, the buffer size requires to
3773 * be multiple of (number of channels * bytes per sample)
3774 * For writes to succeed, the buffer must be written at address which is multiple of 32
3775 */
3776 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3777
3778 return (size/(channel_count * bytes_per_sample));
3779}
3780
Zhou Song48453a02018-01-10 17:50:59 +08003781static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303782{
3783 uint64_t actual_frames_rendered = 0;
3784 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3785
3786 /* This adjustment accounts for buffering after app processor.
3787 * It is based on estimated DSP latency per use case, rather than exact.
3788 */
3789 int64_t platform_latency = platform_render_latency(out->usecase) *
3790 out->sample_rate / 1000000LL;
3791
Zhou Song48453a02018-01-10 17:50:59 +08003792 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303793 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3794 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3795 * hence only estimate.
3796 */
3797 int64_t signed_frames = out->written - kernel_buffer_size;
3798
3799 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3800
Zhou Song48453a02018-01-10 17:50:59 +08003801 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303802 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003803 if (timestamp != NULL )
3804 *timestamp = out->writeAt;
3805 } else if (timestamp != NULL) {
3806 clock_gettime(CLOCK_MONOTONIC, timestamp);
3807 }
3808 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303809
3810 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3811 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3812 (long long int)out->written, (int)kernel_buffer_size,
3813 audio_bytes_per_sample(out->compr_config.codec->format),
3814 popcount(out->channel_mask));
3815
3816 return actual_frames_rendered;
3817}
3818
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003819static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3820{
3821 struct stream_out *out = (struct stream_out *)stream;
3822
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003823 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003824}
3825
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003826static int out_set_sample_rate(struct audio_stream *stream __unused,
3827 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003828{
3829 return -ENOSYS;
3830}
3831
3832static size_t out_get_buffer_size(const struct audio_stream *stream)
3833{
3834 struct stream_out *out = (struct stream_out *)stream;
3835
Varun Balaraje49253e2017-07-06 19:48:56 +05303836 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303837 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303838 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303839 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3840 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3841 else
3842 return out->compr_config.fragment_size;
3843 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003844 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003845 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3846 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 +05303847 else if (is_offload_usecase(out->usecase) &&
3848 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303849 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003850
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003851 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003852 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853}
3854
3855static uint32_t out_get_channels(const struct audio_stream *stream)
3856{
3857 struct stream_out *out = (struct stream_out *)stream;
3858
3859 return out->channel_mask;
3860}
3861
3862static audio_format_t out_get_format(const struct audio_stream *stream)
3863{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003864 struct stream_out *out = (struct stream_out *)stream;
3865
3866 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003867}
3868
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003869static int out_set_format(struct audio_stream *stream __unused,
3870 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871{
3872 return -ENOSYS;
3873}
3874
3875static int out_standby(struct audio_stream *stream)
3876{
3877 struct stream_out *out = (struct stream_out *)stream;
3878 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003879 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003880
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303881 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3882 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003883
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003884 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003885 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003886 if (adev->adm_deregister_stream)
3887 adev->adm_deregister_stream(adev->adm_data, out->handle);
3888
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003889 if (is_offload_usecase(out->usecase))
3890 stop_compressed_output_l(out);
3891
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003892 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003893 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003894 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3895 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303896 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003897 pthread_mutex_unlock(&adev->lock);
3898 pthread_mutex_unlock(&out->lock);
3899 ALOGD("VOIP output entered standby");
3900 return 0;
3901 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003902 if (out->pcm) {
3903 pcm_close(out->pcm);
3904 out->pcm = NULL;
3905 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003906 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3907 do_stop = out->playback_started;
3908 out->playback_started = false;
3909 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003910 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003911 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303912 out->send_next_track_params = false;
3913 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003914 out->gapless_mdata.encoder_delay = 0;
3915 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003916 if (out->compr != NULL) {
3917 compress_close(out->compr);
3918 out->compr = NULL;
3919 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003920 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003921 if (do_stop) {
3922 stop_output_stream(out);
3923 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003924 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003925 }
3926 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303927 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928 return 0;
3929}
3930
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303931static int out_on_error(struct audio_stream *stream)
3932{
3933 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003934 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303935
3936 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003937 // always send CMD_ERROR for offload streams, this
3938 // is needed e.g. when SSR happens within compress_open
3939 // since the stream is active, offload_callback_thread is also active.
3940 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3941 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003942 }
3943 pthread_mutex_unlock(&out->lock);
3944
3945 status = out_standby(&out->stream.common);
3946
3947 lock_output_stream(out);
3948 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003949 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303950 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05303951
3952 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
3953 ALOGD("Setting previous card status if offline");
3954 out->prev_card_status_offline = true;
3955 }
3956
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303957 pthread_mutex_unlock(&out->lock);
3958
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003959 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303960}
3961
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303962/*
3963 *standby implementation without locks, assumes that the callee already
3964 *has taken adev and out lock.
3965 */
3966int out_standby_l(struct audio_stream *stream)
3967{
3968 struct stream_out *out = (struct stream_out *)stream;
3969 struct audio_device *adev = out->dev;
3970
3971 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3972 stream, out->usecase, use_case_table[out->usecase]);
3973
3974 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003975 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303976 if (adev->adm_deregister_stream)
3977 adev->adm_deregister_stream(adev->adm_data, out->handle);
3978
3979 if (is_offload_usecase(out->usecase))
3980 stop_compressed_output_l(out);
3981
3982 out->standby = true;
3983 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3984 voice_extn_compress_voip_close_output_stream(stream);
3985 out->started = 0;
3986 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003987 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303988 return 0;
3989 } else if (!is_offload_usecase(out->usecase)) {
3990 if (out->pcm) {
3991 pcm_close(out->pcm);
3992 out->pcm = NULL;
3993 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003994 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3995 if (adev->haptic_pcm) {
3996 pcm_close(adev->haptic_pcm);
3997 adev->haptic_pcm = NULL;
3998 }
3999
4000 if (adev->haptic_buffer != NULL) {
4001 free(adev->haptic_buffer);
4002 adev->haptic_buffer = NULL;
4003 adev->haptic_buffer_size = 0;
4004 }
4005 adev->haptic_pcm_device_id = 0;
4006 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304007 } else {
4008 ALOGD("copl(%p):standby", out);
4009 out->send_next_track_params = false;
4010 out->is_compr_metadata_avail = false;
4011 out->gapless_mdata.encoder_delay = 0;
4012 out->gapless_mdata.encoder_padding = 0;
4013 if (out->compr != NULL) {
4014 compress_close(out->compr);
4015 out->compr = NULL;
4016 }
4017 }
4018 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004019 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304020 }
4021 ALOGD("%s: exit", __func__);
4022 return 0;
4023}
4024
Aalique Grahame22e49102018-12-18 14:23:57 -08004025static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004026{
Aalique Grahame22e49102018-12-18 14:23:57 -08004027 struct stream_out *out = (struct stream_out *)stream;
4028
4029 // We try to get the lock for consistency,
4030 // but it isn't necessary for these variables.
4031 // If we're not in standby, we may be blocked on a write.
4032 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4033 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4034 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4035
4036 if (locked) {
4037 pthread_mutex_unlock(&out->lock);
4038 }
4039
4040 // dump error info
4041 (void)error_log_dump(
4042 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4043
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004044 return 0;
4045}
4046
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004047static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4048{
4049 int ret = 0;
4050 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004051
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004052 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004053 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004054 return -EINVAL;
4055 }
4056
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304057 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004058
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004059 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4060 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304061 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004062 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004063 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4064 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304065 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004066 }
4067
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004068 ALOGV("%s new encoder delay %u and padding %u", __func__,
4069 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4070
4071 return 0;
4072}
4073
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004074static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4075{
4076 return out == adev->primary_output || out == adev->voice_tx_output;
4077}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004078
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304079// note: this call is safe only if the stream_cb is
4080// removed first in close_output_stream (as is done now).
4081static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4082{
4083 if (!stream || !parms)
4084 return;
4085
4086 struct stream_out *out = (struct stream_out *)stream;
4087 struct audio_device *adev = out->dev;
4088
4089 card_status_t status;
4090 int card;
4091 if (parse_snd_card_status(parms, &card, &status) < 0)
4092 return;
4093
4094 pthread_mutex_lock(&adev->lock);
4095 bool valid_cb = (card == adev->snd_card);
4096 pthread_mutex_unlock(&adev->lock);
4097
4098 if (!valid_cb)
4099 return;
4100
4101 lock_output_stream(out);
4102 if (out->card_status != status)
4103 out->card_status = status;
4104 pthread_mutex_unlock(&out->lock);
4105
4106 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4107 use_case_table[out->usecase],
4108 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4109
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304110 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304111 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304112 if (voice_is_call_state_active(adev) &&
4113 out == adev->primary_output) {
4114 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4115 pthread_mutex_lock(&adev->lock);
4116 voice_stop_call(adev);
4117 adev->mode = AUDIO_MODE_NORMAL;
4118 pthread_mutex_unlock(&adev->lock);
4119 }
4120 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304121 return;
4122}
4123
Kevin Rocardfce19002017-08-07 19:21:36 -07004124static int get_alive_usb_card(struct str_parms* parms) {
4125 int card;
4126 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4127 !audio_extn_usb_alive(card)) {
4128 return card;
4129 }
4130 return -ENODEV;
4131}
4132
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004133static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4134{
4135 struct stream_out *out = (struct stream_out *)stream;
4136 struct audio_device *adev = out->dev;
4137 struct str_parms *parms;
4138 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004139 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304140 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004141 bool reconfig = false;
4142 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004143
sangwoobc677242013-08-08 16:53:43 +09004144 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004145 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004146 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304147 if (!parms)
4148 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004149 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4150 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004151 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004152 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004153 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004154
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004155 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004156 * When HDMI cable is unplugged the music playback is paused and
4157 * the policy manager sends routing=0. But the audioflinger continues
4158 * to write data until standby time (3sec). As the HDMI core is
4159 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004160 * Avoid this by routing audio to speaker until standby.
4161 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004162 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4163 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304164 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004165 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4166 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004167 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304168 /*
4169 * When A2DP is disconnected the
4170 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004171 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304172 * (3sec). As BT is turned off, the write gets blocked.
4173 * Avoid this by routing audio to speaker until standby.
4174 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004175 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004176 (val == AUDIO_DEVICE_NONE) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004177 !audio_extn_a2dp_source_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304178 val = AUDIO_DEVICE_OUT_SPEAKER;
4179 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304180 /*
4181 * When USB headset is disconnected the music platback paused
4182 * and the policy manager send routing=0. But if the USB is connected
4183 * back before the standby time, AFE is not closed and opened
4184 * when USB is connected back. So routing to speker will guarantee
4185 * AFE reconfiguration and AFE will be opend once USB is connected again
4186 */
4187 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4188 (val == AUDIO_DEVICE_NONE) &&
4189 !audio_extn_usb_connected(parms)) {
4190 val = AUDIO_DEVICE_OUT_SPEAKER;
4191 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304192 /* To avoid a2dp to sco overlapping / BT device improper state
4193 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304194 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304195 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004196 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004197 if (val &
4198 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304199 //combo usecase just by pass a2dp
4200 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304201 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304202 } else {
4203 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4204 /* update device to a2dp and don't route as BT returned error
4205 * However it is still possible a2dp routing called because
4206 * of current active device disconnection (like wired headset)
4207 */
4208 out->devices = val;
4209 pthread_mutex_unlock(&out->lock);
4210 pthread_mutex_unlock(&adev->lock);
4211 goto error;
4212 }
4213 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304214 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004215
4216 audio_devices_t new_dev = val;
4217
4218 // Workaround: If routing to an non existing usb device, fail gracefully
4219 // The routing request will otherwise block during 10 second
4220 int card;
4221 if (audio_is_usb_out_device(new_dev) &&
4222 (card = get_alive_usb_card(parms)) >= 0) {
4223
4224 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4225 pthread_mutex_unlock(&adev->lock);
4226 pthread_mutex_unlock(&out->lock);
4227 ret = -ENOSYS;
4228 goto routing_fail;
4229 }
4230
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004231 /*
4232 * select_devices() call below switches all the usecases on the same
4233 * backend to the new device. Refer to check_usecases_codec_backend() in
4234 * the select_devices(). But how do we undo this?
4235 *
4236 * For example, music playback is active on headset (deep-buffer usecase)
4237 * and if we go to ringtones and select a ringtone, low-latency usecase
4238 * will be started on headset+speaker. As we can't enable headset+speaker
4239 * and headset devices at the same time, select_devices() switches the music
4240 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4241 * So when the ringtone playback is completed, how do we undo the same?
4242 *
4243 * We are relying on the out_set_parameters() call on deep-buffer output,
4244 * once the ringtone playback is ended.
4245 * NOTE: We should not check if the current devices are same as new devices.
4246 * Because select_devices() must be called to switch back the music
4247 * playback to headset.
4248 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004249 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004250 audio_devices_t new_dev = val;
4251 bool same_dev = out->devices == new_dev;
4252 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004253
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004254 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004255 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004256 if (adev->mode == AUDIO_MODE_IN_CALL) {
4257 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004258 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4259 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4260 audio_extn_usb_set_service_interval(true /*playback*/,
4261 service_interval,
4262 &reconfig);
4263 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4264 }
4265 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004266 }
4267 } else {
4268 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004269 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004270 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004271 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004272
4273 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004274 if (!same_dev) {
4275 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304276 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4277 adev->perf_lock_opts,
4278 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004279 if (adev->adm_on_routing_change)
4280 adev->adm_on_routing_change(adev->adm_data,
4281 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004282 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304283 if (!bypass_a2dp) {
4284 select_devices(adev, out->usecase);
4285 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004286 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4287 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4288 else
4289 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304290 select_devices(adev, out->usecase);
4291 out->devices = new_dev;
4292 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004293
4294 if (!same_dev) {
4295 // on device switch force swap, lower functions will make sure
4296 // to check if swap is allowed or not.
4297 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304298 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004299 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304300 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4301 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004302 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304303 pthread_mutex_lock(&out->compr_mute_lock);
4304 out->a2dp_compress_mute = false;
4305 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4306 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004307 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4308 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304309 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004310 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004311 }
4312
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004314 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004315
4316 /*handles device and call state changes*/
4317 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004319 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004320
4321 if (out == adev->primary_output) {
4322 pthread_mutex_lock(&adev->lock);
4323 audio_extn_set_parameters(adev, parms);
4324 pthread_mutex_unlock(&adev->lock);
4325 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004326 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004327 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004328 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004329
4330 audio_extn_dts_create_state_notifier_node(out->usecase);
4331 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4332 popcount(out->channel_mask),
4333 out->playback_started);
4334
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004335 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004336 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004337
Surendar Karkaf51b5842018-04-26 11:28:38 +05304338 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4339 sizeof(value));
4340 if (err >= 0) {
4341 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4342 audio_extn_send_dual_mono_mixing_coefficients(out);
4343 }
4344
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304345 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4346 if (err >= 0) {
4347 strlcpy(out->profile, value, sizeof(out->profile));
4348 ALOGV("updating stream profile with value '%s'", out->profile);
4349 lock_output_stream(out);
4350 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4351 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004352 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304353 out->sample_rate, out->bit_width,
4354 out->channel_mask, out->profile,
4355 &out->app_type_cfg);
4356 pthread_mutex_unlock(&out->lock);
4357 }
4358
Alexy Joseph98988832017-01-13 14:56:59 -08004359 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004360 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4361 // and vendor.audio.hal.output.suspend.supported is set to true
4362 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004363 //check suspend parameter only for low latency and if the property
4364 //is enabled
4365 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4366 ALOGI("%s: got suspend_playback %s", __func__, value);
4367 lock_output_stream(out);
4368 if (!strncmp(value, "false", 5)) {
4369 //suspend_playback=false is supposed to set QOS value back to 75%
4370 //the mixer control sent with value Enable will achieve that
4371 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4372 } else if (!strncmp (value, "true", 4)) {
4373 //suspend_playback=true is supposed to remove QOS value
4374 //resetting the mixer control will set the default value
4375 //for the mixer control which is Disable and this removes the QOS vote
4376 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4377 } else {
4378 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4379 " got %s", __func__, value);
4380 ret = -1;
4381 }
4382
4383 if (ret != 0) {
4384 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4385 __func__, out->pm_qos_mixer_path, ret);
4386 }
4387
4388 pthread_mutex_unlock(&out->lock);
4389 }
4390 }
4391 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004392 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304393error:
Eric Laurent994a6932013-07-17 11:51:42 -07004394 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004395 return ret;
4396}
4397
Paul McLeana50b7332018-12-17 08:24:21 -07004398static int in_set_microphone_direction(const struct audio_stream_in *stream,
4399 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004400 struct stream_in *in = (struct stream_in *)stream;
4401
4402 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4403
4404 in->direction = dir;
4405
4406 if (in->standby)
4407 return 0;
4408
4409 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004410}
4411
4412static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004413 struct stream_in *in = (struct stream_in *)stream;
4414
4415 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4416
4417 if (zoom > 1.0 || zoom < -1.0)
4418 return -EINVAL;
4419
4420 in->zoom = zoom;
4421
4422 if (in->standby)
4423 return 0;
4424
4425 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004426}
4427
4428
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004429static bool stream_get_parameter_channels(struct str_parms *query,
4430 struct str_parms *reply,
4431 audio_channel_mask_t *supported_channel_masks) {
4432 int ret = -1;
4433 char value[512];
4434 bool first = true;
4435 size_t i, j;
4436
4437 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4438 ret = 0;
4439 value[0] = '\0';
4440 i = 0;
4441 while (supported_channel_masks[i] != 0) {
4442 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4443 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4444 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304445 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004446
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304447 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004448 first = false;
4449 break;
4450 }
4451 }
4452 i++;
4453 }
4454 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4455 }
4456 return ret == 0;
4457}
4458
4459static bool stream_get_parameter_formats(struct str_parms *query,
4460 struct str_parms *reply,
4461 audio_format_t *supported_formats) {
4462 int ret = -1;
4463 char value[256];
4464 size_t i, j;
4465 bool first = true;
4466
4467 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4468 ret = 0;
4469 value[0] = '\0';
4470 i = 0;
4471 while (supported_formats[i] != 0) {
4472 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4473 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4474 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304475 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004476 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304477 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004478 first = false;
4479 break;
4480 }
4481 }
4482 i++;
4483 }
4484 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4485 }
4486 return ret == 0;
4487}
4488
4489static bool stream_get_parameter_rates(struct str_parms *query,
4490 struct str_parms *reply,
4491 uint32_t *supported_sample_rates) {
4492
4493 int i;
4494 char value[256];
4495 int ret = -1;
4496 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4497 ret = 0;
4498 value[0] = '\0';
4499 i=0;
4500 int cursor = 0;
4501 while (supported_sample_rates[i]) {
4502 int avail = sizeof(value) - cursor;
4503 ret = snprintf(value + cursor, avail, "%s%d",
4504 cursor > 0 ? "|" : "",
4505 supported_sample_rates[i]);
4506 if (ret < 0 || ret >= avail) {
4507 // if cursor is at the last element of the array
4508 // overwrite with \0 is duplicate work as
4509 // snprintf already put a \0 in place.
4510 // else
4511 // we had space to write the '|' at value[cursor]
4512 // (which will be overwritten) or no space to fill
4513 // the first element (=> cursor == 0)
4514 value[cursor] = '\0';
4515 break;
4516 }
4517 cursor += ret;
4518 ++i;
4519 }
4520 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4521 value);
4522 }
4523 return ret >= 0;
4524}
4525
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004526static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4527{
4528 struct stream_out *out = (struct stream_out *)stream;
4529 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004530 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004531 char value[256];
4532 struct str_parms *reply = str_parms_create();
4533 size_t i, j;
4534 int ret;
4535 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004536
4537 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004538 if (reply) {
4539 str_parms_destroy(reply);
4540 }
4541 if (query) {
4542 str_parms_destroy(query);
4543 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004544 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4545 return NULL;
4546 }
4547
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004548 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004549 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4550 if (ret >= 0) {
4551 value[0] = '\0';
4552 i = 0;
4553 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004554 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4555 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004556 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004557 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004558 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004559 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004560 first = false;
4561 break;
4562 }
4563 }
4564 i++;
4565 }
4566 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4567 str = str_parms_to_str(reply);
4568 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004569 voice_extn_out_get_parameters(out, query, reply);
4570 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004571 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004572
Alexy Joseph62142aa2015-11-16 15:10:34 -08004573
4574 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4575 if (ret >= 0) {
4576 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304577 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4578 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004579 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304580 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004581 } else {
4582 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304583 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004584 }
4585 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004586 if (str)
4587 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004588 str = str_parms_to_str(reply);
4589 }
4590
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004591 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4592 if (ret >= 0) {
4593 value[0] = '\0';
4594 i = 0;
4595 first = true;
4596 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004597 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4598 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004599 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004600 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004601 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004602 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004603 first = false;
4604 break;
4605 }
4606 }
4607 i++;
4608 }
4609 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004610 if (str)
4611 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004612 str = str_parms_to_str(reply);
4613 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004614
4615 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4616 if (ret >= 0) {
4617 value[0] = '\0';
4618 i = 0;
4619 first = true;
4620 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004621 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4622 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004623 if (!first) {
4624 strlcat(value, "|", sizeof(value));
4625 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004626 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004627 first = false;
4628 break;
4629 }
4630 }
4631 i++;
4632 }
4633 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4634 if (str)
4635 free(str);
4636 str = str_parms_to_str(reply);
4637 }
4638
Alexy Joseph98988832017-01-13 14:56:59 -08004639 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4640 //only low latency track supports suspend_resume
4641 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004642 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004643 if (str)
4644 free(str);
4645 str = str_parms_to_str(reply);
4646 }
4647
4648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004649 str_parms_destroy(query);
4650 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004651 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004652 return str;
4653}
4654
4655static uint32_t out_get_latency(const struct audio_stream_out *stream)
4656{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004657 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004658 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004659 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004660
Alexy Josephaa54c872014-12-03 02:46:47 -08004661 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304662 lock_output_stream(out);
4663 latency = audio_extn_utils_compress_get_dsp_latency(out);
4664 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004665 } else if ((out->realtime) ||
4666 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004667 // since the buffer won't be filled up faster than realtime,
4668 // return a smaller number
4669 if (out->config.rate)
4670 period_ms = (out->af_period_multiplier * out->config.period_size *
4671 1000) / (out->config.rate);
4672 else
4673 period_ms = 0;
4674 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004675 } else {
4676 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004677 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004678 }
4679
yidongh0515e042017-07-06 15:00:34 +08004680 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004681 latency += audio_extn_a2dp_get_encoder_latency();
4682
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304683 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004684 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004685}
4686
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304687static float AmpToDb(float amplification)
4688{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304689 float db = DSD_VOLUME_MIN_DB;
4690 if (amplification > 0) {
4691 db = 20 * log10(amplification);
4692 if(db < DSD_VOLUME_MIN_DB)
4693 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304694 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304695 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304696}
4697
Arun Mirpuri5d170872019-03-26 13:21:31 -07004698static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4699 float right)
4700{
4701 struct stream_out *out = (struct stream_out *)stream;
4702 long volume = 0;
4703 char mixer_ctl_name[128] = "";
4704 struct audio_device *adev = out->dev;
4705 struct mixer_ctl *ctl = NULL;
4706 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4707 PCM_PLAYBACK);
4708
4709 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4710 "Playback %d Volume", pcm_device_id);
4711 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4712 if (!ctl) {
4713 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4714 __func__, mixer_ctl_name);
4715 return -EINVAL;
4716 }
4717 if (left != right)
4718 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4719 __func__, left, right);
4720 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4721 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4722 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4723 __func__, mixer_ctl_name, volume);
4724 return -EINVAL;
4725 }
4726 return 0;
4727}
4728
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304729static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4730 float right)
4731{
4732 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304733 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304734 char mixer_ctl_name[128];
4735 struct audio_device *adev = out->dev;
4736 struct mixer_ctl *ctl;
4737 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4738 PCM_PLAYBACK);
4739
4740 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4741 "Compress Playback %d Volume", pcm_device_id);
4742 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4743 if (!ctl) {
4744 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4745 __func__, mixer_ctl_name);
4746 return -EINVAL;
4747 }
4748 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4749 __func__, mixer_ctl_name, left, right);
4750 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4751 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4752 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4753
4754 return 0;
4755}
4756
Zhou Song2b8f28f2017-09-11 10:51:38 +08004757static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4758 float right)
4759{
4760 struct stream_out *out = (struct stream_out *)stream;
4761 char mixer_ctl_name[] = "App Type Gain";
4762 struct audio_device *adev = out->dev;
4763 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304764 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004765
4766 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4767 if (!ctl) {
4768 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4769 __func__, mixer_ctl_name);
4770 return -EINVAL;
4771 }
4772
4773 set_values[0] = 0; //0: Rx Session 1:Tx Session
4774 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304775 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4776 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004777
4778 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4779 return 0;
4780}
4781
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304782static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
4783 float right)
4784{
4785 struct stream_out *out = (struct stream_out *)stream;
4786 /* Volume control for pcm playback */
4787 if (left != right) {
4788 return -EINVAL;
4789 } else {
4790 char mixer_ctl_name[128];
4791 struct audio_device *adev = out->dev;
4792 struct mixer_ctl *ctl;
4793 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4794 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
4795 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4796 if (!ctl) {
4797 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
4798 return -EINVAL;
4799 }
4800
4801 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
4802 int ret = mixer_ctl_set_value(ctl, 0, volume);
4803 if (ret < 0) {
4804 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
4805 return -EINVAL;
4806 }
4807
4808 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
4809
4810 return 0;
4811 }
4812}
4813
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004814static int out_set_volume(struct audio_stream_out *stream, float left,
4815 float right)
4816{
Eric Laurenta9024de2013-04-04 09:19:12 -07004817 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004818 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304819 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004820
Arun Mirpuri5d170872019-03-26 13:21:31 -07004821 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07004822 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4823 /* only take left channel into account: the API is for stereo anyway */
4824 out->muted = (left == 0.0f);
4825 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004826 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304827 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004828 /*
4829 * Set mute or umute on HDMI passthrough stream.
4830 * Only take left channel into account.
4831 * Mute is 0 and unmute 1
4832 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304833 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304834 } else if (out->format == AUDIO_FORMAT_DSD){
4835 char mixer_ctl_name[128] = "DSD Volume";
4836 struct audio_device *adev = out->dev;
4837 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4838
4839 if (!ctl) {
4840 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4841 __func__, mixer_ctl_name);
4842 return -EINVAL;
4843 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304844 volume[0] = (long)(AmpToDb(left));
4845 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304846 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4847 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004848 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304849 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07004850 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304851 if (!out->a2dp_compress_mute)
4852 ret = out_set_compr_volume(stream, left, right);
4853 out->volume_l = left;
4854 out->volume_r = right;
4855 pthread_mutex_unlock(&out->compr_mute_lock);
4856 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004857 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004858 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004859 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
4860 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
4861 if (!out->standby) {
4862 audio_extn_utils_send_app_type_gain(out->dev,
4863 out->app_type_cfg.app_type,
4864 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004865 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08004866 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08004867 out->volume_l = left;
4868 out->volume_r = right;
4869 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07004870 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4871 ALOGV("%s: MMAP set volume called", __func__);
4872 if (!out->standby)
4873 ret = out_set_mmap_volume(stream, left, right);
4874 out->volume_l = left;
4875 out->volume_r = right;
4876 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304877 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05304878 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4879 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304880 /* Volume control for pcm playback */
4881 if (!out->standby)
4882 ret = out_set_pcm_volume(stream, left, right);
4883 else
4884 out->apply_volume = true;
4885
4886 out->volume_l = left;
4887 out->volume_r = right;
4888 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004889 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004891 return -ENOSYS;
4892}
4893
Zhou Songc9672822017-08-16 16:01:39 +08004894static void update_frames_written(struct stream_out *out, size_t bytes)
4895{
4896 size_t bpf = 0;
4897
4898 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4899 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4900 bpf = 1;
4901 else if (!is_offload_usecase(out->usecase))
4902 bpf = audio_bytes_per_sample(out->format) *
4903 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004904
4905 pthread_mutex_lock(&out->position_query_lock);
4906 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004907 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004908 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4909 }
4910 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004911}
4912
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004913int split_and_write_audio_haptic_data(struct stream_out *out,
4914 const void *buffer, size_t bytes_to_write)
4915{
4916 struct audio_device *adev = out->dev;
4917
4918 int ret = 0;
4919 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4920 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
4921 size_t frame_size = channel_count * bytes_per_sample;
4922 size_t frame_count = bytes_to_write / frame_size;
4923
4924 bool force_haptic_path =
4925 property_get_bool("vendor.audio.test_haptic", false);
4926
4927 // extract Haptics data from Audio buffer
4928 bool alloc_haptic_buffer = false;
4929 int haptic_channel_count = adev->haptics_config.channels;
4930 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
4931 size_t audio_frame_size = frame_size - haptic_frame_size;
4932 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
4933
4934 if (adev->haptic_buffer == NULL) {
4935 alloc_haptic_buffer = true;
4936 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
4937 free(adev->haptic_buffer);
4938 adev->haptic_buffer_size = 0;
4939 alloc_haptic_buffer = true;
4940 }
4941
4942 if (alloc_haptic_buffer) {
4943 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
4944 adev->haptic_buffer_size = total_haptic_buffer_size;
4945 }
4946
4947 size_t src_index = 0, aud_index = 0, hap_index = 0;
4948 uint8_t *audio_buffer = (uint8_t *)buffer;
4949 uint8_t *haptic_buffer = adev->haptic_buffer;
4950
4951 // This is required for testing only. This works for stereo data only.
4952 // One channel is fed to audio stream and other to haptic stream for testing.
4953 if (force_haptic_path)
4954 audio_frame_size = haptic_frame_size = bytes_per_sample;
4955
4956 for (size_t i = 0; i < frame_count; i++) {
4957 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
4958 audio_frame_size);
4959 aud_index += audio_frame_size;
4960 src_index += audio_frame_size;
4961
4962 if (adev->haptic_pcm)
4963 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
4964 haptic_frame_size);
4965 hap_index += haptic_frame_size;
4966 src_index += haptic_frame_size;
4967
4968 // This is required for testing only.
4969 // Discard haptic channel data.
4970 if (force_haptic_path)
4971 src_index += haptic_frame_size;
4972 }
4973
4974 // write to audio pipeline
4975 ret = pcm_write(out->pcm, (void *)audio_buffer,
4976 frame_count * audio_frame_size);
4977
4978 // write to haptics pipeline
4979 if (adev->haptic_pcm)
4980 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
4981 frame_count * haptic_frame_size);
4982
4983 return ret;
4984}
4985
Aalique Grahame22e49102018-12-18 14:23:57 -08004986#ifdef NO_AUDIO_OUT
4987static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
4988 const void *buffer __unused, size_t bytes)
4989{
4990 struct stream_out *out = (struct stream_out *)stream;
4991
4992 /* No Output device supported other than BT for playback.
4993 * Sleep for the amount of buffer duration
4994 */
4995 lock_output_stream(out);
4996 usleep(bytes * 1000000 / audio_stream_out_frame_size(
4997 (const struct audio_stream_out *)&out->stream) /
4998 out_get_sample_rate(&out->stream.common));
4999 pthread_mutex_unlock(&out->lock);
5000 return bytes;
5001}
5002#endif
5003
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005004static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5005 size_t bytes)
5006{
5007 struct stream_out *out = (struct stream_out *)stream;
5008 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005009 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305010 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005011 const size_t frame_size = audio_stream_out_frame_size(stream);
5012 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305013 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005014
Haynes Mathew George380745d2017-10-04 15:27:45 -07005015 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005016 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305017
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305018 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005019
Dhananjay Kumarac341582017-02-23 23:42:25 +05305020 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305021 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305022 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5023 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005024 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305025 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305026 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305027 ALOGD(" %s: sound card is not active/SSR state", __func__);
5028 ret= -EIO;
5029 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305030 }
5031 }
5032
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305033 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305034 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305035 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305036 goto exit;
5037 }
5038
Haynes Mathew George16081042017-05-31 17:16:49 -07005039 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5040 ret = -EINVAL;
5041 goto exit;
5042 }
5043
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305044 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5045 !out->is_iec61937_info_available) {
5046
5047 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5048 out->is_iec61937_info_available = true;
5049 } else if (audio_extn_passthru_is_enabled()) {
5050 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305051 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305052
5053 if((out->format == AUDIO_FORMAT_DTS) ||
5054 (out->format == AUDIO_FORMAT_DTS_HD)) {
5055 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5056 buffer, bytes);
5057 if (ret) {
5058 if (ret != -ENOSYS) {
5059 out->is_iec61937_info_available = false;
5060 ALOGD("iec61937 transmission info not yet updated retry");
5061 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305062 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305063 /* if stream has started and after that there is
5064 * stream config change (iec transmission config)
5065 * then trigger select_device to update backend configuration.
5066 */
5067 out->stream_config_changed = true;
5068 pthread_mutex_lock(&adev->lock);
5069 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305070 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
5071 ret = -EINVAL;
5072 goto exit;
5073 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305074 pthread_mutex_unlock(&adev->lock);
5075 out->stream_config_changed = false;
5076 out->is_iec61937_info_available = true;
5077 }
5078 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305079
Garmond Leung317cbf12017-09-13 16:20:50 -07005080 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305081 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
5082 (out->is_iec61937_info_available == true)) {
5083 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5084 ret = -EINVAL;
5085 goto exit;
5086 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305087 }
5088 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305089
5090 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005091 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005092 if (!(out->devices &
5093 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305094 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305095 ret = -EIO;
5096 goto exit;
5097 }
5098 }
5099 }
5100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005101 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005102 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005103 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005104 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5105 ret = voice_extn_compress_voip_start_output_stream(out);
5106 else
5107 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005108 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005109 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005110 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005111 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005112 goto exit;
5113 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305114 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005115 if (last_known_cal_step != -1) {
5116 ALOGD("%s: retry previous failed cal level set", __func__);
5117 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305118 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005119 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305120
5121 if ((out->is_iec61937_info_available == true) &&
5122 (audio_extn_passthru_is_passthrough_stream(out))&&
5123 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5124 ret = -EINVAL;
5125 goto exit;
5126 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305127 if (out->set_dual_mono)
5128 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005129 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005130
Ashish Jain81eb2a82015-05-13 10:52:34 +05305131 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005132 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305133 adev->is_channel_status_set = true;
5134 }
5135
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305136 if ((adev->use_old_pspd_mix_ctrl == true) &&
5137 (out->pspd_coeff_sent == false)) {
5138 /*
5139 * Need to resend pspd coefficients after stream started for
5140 * older kernel version as it does not save the coefficients
5141 * and also stream has to be started for coeff to apply.
5142 */
5143 usecase = get_usecase_from_list(adev, out->usecase);
5144 if (usecase != NULL) {
5145 audio_extn_set_custom_mtmx_params(adev, usecase, true);
5146 out->pspd_coeff_sent = true;
5147 }
5148 }
5149
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005150 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005151 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005152 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005153 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005154 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5155 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305156 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5157 ALOGD("copl(%p):send next track params in gapless", out);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005158 // compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305159 out->send_next_track_params = false;
5160 out->is_compr_metadata_avail = false;
5161 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005162 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305163 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305164 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005165
Ashish Jain83a6cc22016-06-28 14:34:17 +05305166 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305167 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305168 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305169 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005170 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305171 return -EINVAL;
5172 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305173 audio_format_t dst_format = out->hal_op_format;
5174 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305175
Dieter Luecking5d57def2018-09-07 14:23:37 +02005176 /* prevent division-by-zero */
5177 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5178 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5179 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5180 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305181 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005182 ATRACE_END();
5183 return -EINVAL;
5184 }
5185
Ashish Jainf1eaa582016-05-23 20:54:24 +05305186 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5187 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5188
Ashish Jain83a6cc22016-06-28 14:34:17 +05305189 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305190 dst_format,
5191 buffer,
5192 src_format,
5193 frames);
5194
Ashish Jain83a6cc22016-06-28 14:34:17 +05305195 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305196 bytes_to_write);
5197
5198 /*Convert written bytes in audio flinger format*/
5199 if (ret > 0)
5200 ret = ((ret * format_to_bitwidth_table[out->format]) /
5201 format_to_bitwidth_table[dst_format]);
5202 }
5203 } else
5204 ret = compress_write(out->compr, buffer, bytes);
5205
Zhou Songc9672822017-08-16 16:01:39 +08005206 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5207 update_frames_written(out, bytes);
5208
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305209 if (ret < 0)
5210 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005211 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305212 /*msg to cb thread only if non blocking write is enabled*/
5213 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305214 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005215 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305216 } else if (-ENETRESET == ret) {
5217 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305218 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305219 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305220 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005221 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305222 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005223 }
Ashish Jain5106d362016-05-11 19:23:33 +05305224
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305225 /* Call compr start only when non-zero bytes of data is there to be rendered */
5226 if (!out->playback_started && ret > 0) {
5227 int status = compress_start(out->compr);
5228 if (status < 0) {
5229 ret = status;
5230 ALOGE("%s: compr start failed with err %d", __func__, errno);
5231 goto exit;
5232 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005233 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005234 out->playback_started = 1;
5235 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005236
5237 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5238 popcount(out->channel_mask),
5239 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005240 }
5241 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005242 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005243 return ret;
5244 } else {
5245 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005246 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005247 if (out->muted)
5248 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005249 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5250 __func__, frames, frame_size, bytes_to_write);
5251
Aalique Grahame22e49102018-12-18 14:23:57 -08005252 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aalique Grahame22e49102018-12-18 14:23:57 -08005253 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005254 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5255 int16_t *src = (int16_t *)buffer;
5256 int16_t *dst = (int16_t *)buffer;
5257
5258 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5259 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005260 "out_write called for %s use case with wrong properties",
5261 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005262
5263 /*
5264 * FIXME: this can be removed once audio flinger mixer supports
5265 * mono output
5266 */
5267
5268 /*
5269 * Code below goes over each frame in the buffer and adds both
5270 * L and R samples and then divides by 2 to convert to mono
5271 */
5272 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5273 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5274 }
5275 bytes_to_write /= 2;
5276 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005277
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305278 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005279
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005280 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005281
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005282 if (out->config.rate)
5283 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5284 out->config.rate;
5285
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005286 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005287 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5288
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005289 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005290 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005291 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305292 out->convert_buffer != NULL) {
5293
5294 memcpy_by_audio_format(out->convert_buffer,
5295 out->hal_op_format,
5296 buffer,
5297 out->hal_ip_format,
5298 out->config.period_size * out->config.channels);
5299
5300 ret = pcm_write(out->pcm, out->convert_buffer,
5301 (out->config.period_size *
5302 out->config.channels *
5303 format_to_bitwidth_table[out->hal_op_format]));
5304 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305305 /*
5306 * To avoid underrun in DSP when the application is not pumping
5307 * data at required rate, check for the no. of bytes and ignore
5308 * pcm_write if it is less than actual buffer size.
5309 * It is a work around to a change in compress VOIP driver.
5310 */
5311 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5312 bytes < (out->config.period_size * out->config.channels *
5313 audio_bytes_per_sample(out->format))) {
5314 size_t voip_buf_size =
5315 out->config.period_size * out->config.channels *
5316 audio_bytes_per_sample(out->format);
5317 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5318 __func__, bytes, voip_buf_size);
5319 usleep(((uint64_t)voip_buf_size - bytes) *
5320 1000000 / audio_stream_out_frame_size(stream) /
5321 out_get_sample_rate(&out->stream.common));
5322 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005323 } else {
5324 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5325 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5326 else
5327 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5328 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305329 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005330
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005331 release_out_focus(out);
5332
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305333 if (ret < 0)
5334 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005335 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305336 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005337 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005338 }
5339
5340exit:
Zhou Songc9672822017-08-16 16:01:39 +08005341 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305342 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305343 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305344 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005345 pthread_mutex_unlock(&out->lock);
5346
5347 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005348 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005349 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305350 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305351 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305352 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305353 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305354 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305355 out->standby = true;
5356 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305357 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005358 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5359 /* prevent division-by-zero */
5360 uint32_t stream_size = audio_stream_out_frame_size(stream);
5361 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005362
Dieter Luecking5d57def2018-09-07 14:23:37 +02005363 if ((stream_size == 0) || (srate == 0)) {
5364 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5365 ATRACE_END();
5366 return -EINVAL;
5367 }
5368 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5369 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005370 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305371 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005372 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005373 return ret;
5374 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005375 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005376 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005377 return bytes;
5378}
5379
5380static int out_get_render_position(const struct audio_stream_out *stream,
5381 uint32_t *dsp_frames)
5382{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005383 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005384
5385 if (dsp_frames == NULL)
5386 return -EINVAL;
5387
5388 *dsp_frames = 0;
5389 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005390 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305391
5392 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5393 * this operation and adev_close_output_stream(where out gets reset).
5394 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305395 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005396 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305397 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005398 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305399 return 0;
5400 }
5401
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005402 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305403 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305404 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005405 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305406 if (ret < 0)
5407 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005408 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305409 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005410 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305411 if (-ENETRESET == ret) {
5412 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305413 out->card_status = CARD_STATUS_OFFLINE;
5414 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305415 } else if(ret < 0) {
5416 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305417 ret = -EINVAL;
5418 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305419 /*
5420 * Handle corner case where compress session is closed during SSR
5421 * and timestamp is queried
5422 */
5423 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305424 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305425 } else if (out->prev_card_status_offline) {
5426 ALOGE("ERROR: previously sound card was offline,return error");
5427 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305428 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305429 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005430 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305431 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305432 pthread_mutex_unlock(&out->lock);
5433 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005434 } else if (audio_is_linear_pcm(out->format)) {
5435 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005436 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005437 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005438 } else
5439 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005440}
5441
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005442static int out_add_audio_effect(const struct audio_stream *stream __unused,
5443 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005444{
5445 return 0;
5446}
5447
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005448static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5449 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005450{
5451 return 0;
5452}
5453
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005454static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5455 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005456{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305457 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005458}
5459
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005460static int out_get_presentation_position(const struct audio_stream_out *stream,
5461 uint64_t *frames, struct timespec *timestamp)
5462{
5463 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305464 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005465 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005466
Ashish Jain5106d362016-05-11 19:23:33 +05305467 /* below piece of code is not guarded against any lock because audioFliner serializes
5468 * this operation and adev_close_output_stream( where out gets reset).
5469 */
5470 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305471 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005472 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305473 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5474 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5475 return 0;
5476 }
5477
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005478 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005479
Ashish Jain5106d362016-05-11 19:23:33 +05305480 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5481 ret = compress_get_tstamp(out->compr, &dsp_frames,
5482 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005483 // Adjustment accounts for A2dp encoder latency with offload usecases
5484 // Note: Encoder latency is returned in ms.
5485 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5486 unsigned long offset =
5487 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5488 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5489 }
Ashish Jain5106d362016-05-11 19:23:33 +05305490 ALOGVV("%s rendered frames %ld sample_rate %d",
5491 __func__, dsp_frames, out->sample_rate);
5492 *frames = dsp_frames;
5493 if (ret < 0)
5494 ret = -errno;
5495 if (-ENETRESET == ret) {
5496 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305497 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305498 ret = -EINVAL;
5499 } else
5500 ret = 0;
5501 /* this is the best we can do */
5502 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005503 } else {
5504 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005505 unsigned int avail;
5506 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5507 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5508 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5509 // This adjustment accounts for buffering after app processor.
5510 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005511 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005512 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005513
Weiyin Jiangd4633762018-03-16 12:05:03 +08005514 // Adjustment accounts for A2dp encoder latency with non offload usecases
5515 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5516 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5517 signed_frames -=
5518 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5519 }
5520
5521 // It would be unusual for this value to be negative, but check just in case ...
5522 if (signed_frames >= 0) {
5523 *frames = signed_frames;
5524 ret = 0;
5525 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005526 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305527 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305528 *frames = out->written;
5529 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305530 if (is_offload_usecase(out->usecase))
5531 ret = -EINVAL;
5532 else
5533 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005534 }
5535 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005536 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005537 return ret;
5538}
5539
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005540static int out_set_callback(struct audio_stream_out *stream,
5541 stream_callback_t callback, void *cookie)
5542{
5543 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005544 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005545
5546 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005547 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005548 out->client_callback = callback;
5549 out->client_cookie = cookie;
5550 if (out->adsp_hdlr_stream_handle) {
5551 ret = audio_extn_adsp_hdlr_stream_set_callback(
5552 out->adsp_hdlr_stream_handle,
5553 callback,
5554 cookie);
5555 if (ret)
5556 ALOGW("%s:adsp hdlr callback registration failed %d",
5557 __func__, ret);
5558 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005559 pthread_mutex_unlock(&out->lock);
5560 return 0;
5561}
5562
5563static int out_pause(struct audio_stream_out* stream)
5564{
5565 struct stream_out *out = (struct stream_out *)stream;
5566 int status = -ENOSYS;
5567 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005568 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005569 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005570 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005571 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305572 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305573 status = compress_pause(out->compr);
5574
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005575 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005576
Mingming Yin21854652016-04-13 11:54:02 -07005577 if (audio_extn_passthru_is_active()) {
5578 ALOGV("offload use case, pause passthru");
5579 audio_extn_passthru_on_pause(out);
5580 }
5581
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305582 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005583 audio_extn_dts_notify_playback_state(out->usecase, 0,
5584 out->sample_rate, popcount(out->channel_mask),
5585 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005586 }
5587 pthread_mutex_unlock(&out->lock);
5588 }
5589 return status;
5590}
5591
5592static int out_resume(struct audio_stream_out* stream)
5593{
5594 struct stream_out *out = (struct stream_out *)stream;
5595 int status = -ENOSYS;
5596 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005597 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005598 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005599 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005600 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005601 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305602 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305603 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005604 }
5605 if (!status) {
5606 out->offload_state = OFFLOAD_STATE_PLAYING;
5607 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305608 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005609 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5610 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005611 }
5612 pthread_mutex_unlock(&out->lock);
5613 }
5614 return status;
5615}
5616
5617static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5618{
5619 struct stream_out *out = (struct stream_out *)stream;
5620 int status = -ENOSYS;
5621 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005622 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005623 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005624 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5625 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5626 else
5627 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5628 pthread_mutex_unlock(&out->lock);
5629 }
5630 return status;
5631}
5632
5633static int out_flush(struct audio_stream_out* stream)
5634{
5635 struct stream_out *out = (struct stream_out *)stream;
5636 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005637 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005638 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005639 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005640 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5641 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005642 } else {
5643 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5644 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005645 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005646 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005647 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005648 return 0;
5649 }
5650 return -ENOSYS;
5651}
5652
Haynes Mathew George16081042017-05-31 17:16:49 -07005653static int out_stop(const struct audio_stream_out* stream)
5654{
5655 struct stream_out *out = (struct stream_out *)stream;
5656 struct audio_device *adev = out->dev;
5657 int ret = -ENOSYS;
5658
5659 ALOGV("%s", __func__);
5660 pthread_mutex_lock(&adev->lock);
5661 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5662 out->playback_started && out->pcm != NULL) {
5663 pcm_stop(out->pcm);
5664 ret = stop_output_stream(out);
5665 out->playback_started = false;
5666 }
5667 pthread_mutex_unlock(&adev->lock);
5668 return ret;
5669}
5670
5671static int out_start(const struct audio_stream_out* stream)
5672{
5673 struct stream_out *out = (struct stream_out *)stream;
5674 struct audio_device *adev = out->dev;
5675 int ret = -ENOSYS;
5676
5677 ALOGV("%s", __func__);
5678 pthread_mutex_lock(&adev->lock);
5679 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5680 !out->playback_started && out->pcm != NULL) {
5681 ret = start_output_stream(out);
5682 if (ret == 0) {
5683 out->playback_started = true;
5684 }
5685 }
5686 pthread_mutex_unlock(&adev->lock);
5687 return ret;
5688}
5689
5690/*
5691 * Modify config->period_count based on min_size_frames
5692 */
5693static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5694{
5695 int periodCountRequested = (min_size_frames + config->period_size - 1)
5696 / config->period_size;
5697 int periodCount = MMAP_PERIOD_COUNT_MIN;
5698
5699 ALOGV("%s original config.period_size = %d config.period_count = %d",
5700 __func__, config->period_size, config->period_count);
5701
5702 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5703 periodCount *= 2;
5704 }
5705 config->period_count = periodCount;
5706
5707 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5708}
5709
5710static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5711 int32_t min_size_frames,
5712 struct audio_mmap_buffer_info *info)
5713{
5714 struct stream_out *out = (struct stream_out *)stream;
5715 struct audio_device *adev = out->dev;
5716 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005717 unsigned int offset1 = 0;
5718 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005719 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005720 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005721 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005722
Arun Mirpuri5d170872019-03-26 13:21:31 -07005723 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305724 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005725 pthread_mutex_lock(&adev->lock);
5726
Sharad Sanglec6f32552018-05-04 16:15:38 +05305727 if (CARD_STATUS_OFFLINE == out->card_status ||
5728 CARD_STATUS_OFFLINE == adev->card_status) {
5729 ALOGW("out->card_status or adev->card_status offline, try again");
5730 ret = -EIO;
5731 goto exit;
5732 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005733 if (info == NULL || min_size_frames == 0) {
5734 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5735 ret = -EINVAL;
5736 goto exit;
5737 }
5738 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5739 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5740 ret = -ENOSYS;
5741 goto exit;
5742 }
5743 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5744 if (out->pcm_device_id < 0) {
5745 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5746 __func__, out->pcm_device_id, out->usecase);
5747 ret = -EINVAL;
5748 goto exit;
5749 }
5750
5751 adjust_mmap_period_count(&out->config, min_size_frames);
5752
Arun Mirpuri5d170872019-03-26 13:21:31 -07005753 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005754 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5755 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5756 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305757 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305758 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5759 out->card_status = CARD_STATUS_OFFLINE;
5760 adev->card_status = CARD_STATUS_OFFLINE;
5761 ret = -EIO;
5762 goto exit;
5763 }
5764
Haynes Mathew George16081042017-05-31 17:16:49 -07005765 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5766 step = "open";
5767 ret = -ENODEV;
5768 goto exit;
5769 }
5770 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5771 if (ret < 0) {
5772 step = "begin";
5773 goto exit;
5774 }
5775 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005776 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005777 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005778 ret = platform_get_mmap_data_fd(adev->platform,
5779 out->pcm_device_id, 0 /*playback*/,
5780 &info->shared_memory_fd,
5781 &mmap_size);
5782 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07005783 // Fall back to non exclusive mode
5784 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5785 } else {
5786 if (mmap_size < buffer_size) {
5787 step = "mmap";
5788 goto exit;
5789 }
5790 // FIXME: indicate exclusive mode support by returning a negative buffer size
5791 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005792 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005793 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005794 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005795
5796 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5797 if (ret < 0) {
5798 step = "commit";
5799 goto exit;
5800 }
5801
5802 out->standby = false;
5803 ret = 0;
5804
Arun Mirpuri5d170872019-03-26 13:21:31 -07005805 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005806 __func__, info->shared_memory_address, info->buffer_size_frames);
5807
5808exit:
5809 if (ret != 0) {
5810 if (out->pcm == NULL) {
5811 ALOGE("%s: %s - %d", __func__, step, ret);
5812 } else {
5813 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5814 pcm_close(out->pcm);
5815 out->pcm = NULL;
5816 }
5817 }
5818 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305819 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005820 return ret;
5821}
5822
5823static int out_get_mmap_position(const struct audio_stream_out *stream,
5824 struct audio_mmap_position *position)
5825{
5826 struct stream_out *out = (struct stream_out *)stream;
5827 ALOGVV("%s", __func__);
5828 if (position == NULL) {
5829 return -EINVAL;
5830 }
5831 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005832 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005833 return -ENOSYS;
5834 }
5835 if (out->pcm == NULL) {
5836 return -ENOSYS;
5837 }
5838
5839 struct timespec ts = { 0, 0 };
5840 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5841 if (ret < 0) {
5842 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5843 return ret;
5844 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005845 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005846 return 0;
5847}
5848
5849
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005850/** audio_stream_in implementation **/
5851static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5852{
5853 struct stream_in *in = (struct stream_in *)stream;
5854
5855 return in->config.rate;
5856}
5857
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005858static int in_set_sample_rate(struct audio_stream *stream __unused,
5859 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005860{
5861 return -ENOSYS;
5862}
5863
5864static size_t in_get_buffer_size(const struct audio_stream *stream)
5865{
5866 struct stream_in *in = (struct stream_in *)stream;
5867
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005868 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5869 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005870 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5871 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 -07005872 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5873 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305874 else if(audio_extn_cin_attached_usecase(in->usecase))
5875 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005876
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005877 return in->config.period_size * in->af_period_multiplier *
5878 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005879}
5880
5881static uint32_t in_get_channels(const struct audio_stream *stream)
5882{
5883 struct stream_in *in = (struct stream_in *)stream;
5884
5885 return in->channel_mask;
5886}
5887
5888static audio_format_t in_get_format(const struct audio_stream *stream)
5889{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005890 struct stream_in *in = (struct stream_in *)stream;
5891
5892 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005893}
5894
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005895static int in_set_format(struct audio_stream *stream __unused,
5896 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005897{
5898 return -ENOSYS;
5899}
5900
5901static int in_standby(struct audio_stream *stream)
5902{
5903 struct stream_in *in = (struct stream_in *)stream;
5904 struct audio_device *adev = in->dev;
5905 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305906 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5907 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005908 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305909
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005910 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005911 if (!in->standby && in->is_st_session) {
5912 ALOGD("%s: sound trigger pcm stop lab", __func__);
5913 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08005914 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005915 in->standby = 1;
5916 }
5917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005918 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005919 if (adev->adm_deregister_stream)
5920 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5921
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005922 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005923 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005924 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005925 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005926 voice_extn_compress_voip_close_input_stream(stream);
5927 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005928 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5929 do_stop = in->capture_started;
5930 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005931 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305932 if (audio_extn_cin_attached_usecase(in->usecase))
5933 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005934 }
5935
Arun Mirpuri5d170872019-03-26 13:21:31 -07005936 if (in->pcm) {
5937 ATRACE_BEGIN("pcm_in_close");
5938 pcm_close(in->pcm);
5939 ATRACE_END();
5940 in->pcm = NULL;
5941 }
5942
5943 if(do_stop) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005944 adev->enable_voicerx = false;
5945 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Zhou Songa8895042016-07-05 17:54:22 +08005946 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005947 }
Quinn Malef6050362019-01-30 15:55:40 -08005948
5949 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
5950 adev->num_va_sessions--;
5951
Eric Laurent150dbfe2013-02-27 14:31:02 -08005952 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005953 }
5954 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005955 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005956 return status;
5957}
5958
Aalique Grahame22e49102018-12-18 14:23:57 -08005959static int in_dump(const struct audio_stream *stream,
5960 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005961{
Aalique Grahame22e49102018-12-18 14:23:57 -08005962 struct stream_in *in = (struct stream_in *)stream;
5963
5964 // We try to get the lock for consistency,
5965 // but it isn't necessary for these variables.
5966 // If we're not in standby, we may be blocked on a read.
5967 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
5968 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
5969 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
5970 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
5971
5972 if (locked) {
5973 pthread_mutex_unlock(&in->lock);
5974 }
5975
5976 // dump error info
5977 (void)error_log_dump(
5978 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
5979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005980 return 0;
5981}
5982
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305983static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5984{
5985 if (!stream || !parms)
5986 return;
5987
5988 struct stream_in *in = (struct stream_in *)stream;
5989 struct audio_device *adev = in->dev;
5990
5991 card_status_t status;
5992 int card;
5993 if (parse_snd_card_status(parms, &card, &status) < 0)
5994 return;
5995
5996 pthread_mutex_lock(&adev->lock);
5997 bool valid_cb = (card == adev->snd_card);
5998 pthread_mutex_unlock(&adev->lock);
5999
6000 if (!valid_cb)
6001 return;
6002
6003 lock_input_stream(in);
6004 if (in->card_status != status)
6005 in->card_status = status;
6006 pthread_mutex_unlock(&in->lock);
6007
6008 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6009 use_case_table[in->usecase],
6010 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6011
6012 // a better solution would be to report error back to AF and let
6013 // it put the stream to standby
6014 if (status == CARD_STATUS_OFFLINE)
6015 in_standby(&in->stream.common);
6016
6017 return;
6018}
6019
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006020static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6021{
6022 struct stream_in *in = (struct stream_in *)stream;
6023 struct audio_device *adev = in->dev;
6024 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006025 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006026 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006027
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306028 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006029 parms = str_parms_create_str(kvpairs);
6030
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306031 if (!parms)
6032 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006033 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006034 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006035
6036 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
6037 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006038 val = atoi(value);
6039 /* no audio source uses val == 0 */
6040 if ((in->source != val) && (val != 0)) {
6041 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006042 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6043 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6044 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006045 (in->config.rate == 8000 || in->config.rate == 16000 ||
6046 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006047 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006048 err = voice_extn_compress_voip_open_input_stream(in);
6049 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006050 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006051 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006052 }
6053 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006054 }
6055 }
6056
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006057 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
6058 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006059 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07006060 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
6061
6062 // Workaround: If routing to an non existing usb device, fail gracefully
6063 // The routing request will otherwise block during 10 second
6064 int card;
6065 if (audio_is_usb_in_device(val) &&
6066 (card = get_alive_usb_card(parms)) >= 0) {
6067
6068 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
6069 ret = -ENOSYS;
6070 } else {
6071
6072 in->device = val;
6073 /* If recording is in progress, change the tx device to new device */
6074 if (!in->standby && !in->is_st_session) {
6075 ALOGV("update input routing change");
6076 // inform adm before actual routing to prevent glitches.
6077 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07006078 adev->adm_on_routing_change(adev->adm_data,
6079 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07006080 ret = select_devices(adev, in->usecase);
6081 }
6082 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006083 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006084 }
6085 }
6086
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306087 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6088 if (err >= 0) {
6089 strlcpy(in->profile, value, sizeof(in->profile));
6090 ALOGV("updating stream profile with value '%s'", in->profile);
6091 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6092 &adev->streams_input_cfg_list,
6093 in->device, in->flags, in->format,
6094 in->sample_rate, in->bit_width,
6095 in->profile, &in->app_type_cfg);
6096 }
6097
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006098 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006099 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006100
6101 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306102error:
Eric Laurent994a6932013-07-17 11:51:42 -07006103 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006104 return ret;
6105}
6106
6107static char* in_get_parameters(const struct audio_stream *stream,
6108 const char *keys)
6109{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006110 struct stream_in *in = (struct stream_in *)stream;
6111 struct str_parms *query = str_parms_create_str(keys);
6112 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006113 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006114
6115 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006116 if (reply) {
6117 str_parms_destroy(reply);
6118 }
6119 if (query) {
6120 str_parms_destroy(query);
6121 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006122 ALOGE("in_get_parameters: failed to create query or reply");
6123 return NULL;
6124 }
6125
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006126 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006127
6128 voice_extn_in_get_parameters(in, query, reply);
6129
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006130 stream_get_parameter_channels(query, reply,
6131 &in->supported_channel_masks[0]);
6132 stream_get_parameter_formats(query, reply,
6133 &in->supported_formats[0]);
6134 stream_get_parameter_rates(query, reply,
6135 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006136 str = str_parms_to_str(reply);
6137 str_parms_destroy(query);
6138 str_parms_destroy(reply);
6139
6140 ALOGV("%s: exit: returns - %s", __func__, str);
6141 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006142}
6143
Aalique Grahame22e49102018-12-18 14:23:57 -08006144static int in_set_gain(struct audio_stream_in *stream,
6145 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006146{
Aalique Grahame22e49102018-12-18 14:23:57 -08006147 struct stream_in *in = (struct stream_in *)stream;
6148 char mixer_ctl_name[128];
6149 struct mixer_ctl *ctl;
6150 int ctl_value;
6151
6152 ALOGV("%s: gain %f", __func__, gain);
6153
6154 if (stream == NULL)
6155 return -EINVAL;
6156
6157 /* in_set_gain() only used to silence MMAP capture for now */
6158 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6159 return -ENOSYS;
6160
6161 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6162
6163 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6164 if (!ctl) {
6165 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6166 __func__, mixer_ctl_name);
6167 return -ENOSYS;
6168 }
6169
6170 if (gain < RECORD_GAIN_MIN)
6171 gain = RECORD_GAIN_MIN;
6172 else if (gain > RECORD_GAIN_MAX)
6173 gain = RECORD_GAIN_MAX;
6174 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6175
6176 mixer_ctl_set_value(ctl, 0, ctl_value);
6177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006178 return 0;
6179}
6180
6181static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6182 size_t bytes)
6183{
6184 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306185
6186 if (in == NULL) {
6187 ALOGE("%s: stream_in ptr is NULL", __func__);
6188 return -EINVAL;
6189 }
6190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006191 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306192 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306193 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006194
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006195 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306196
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006197 if (in->is_st_session) {
6198 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6199 /* Read from sound trigger HAL */
6200 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006201 if (in->standby) {
6202 adev->num_va_sessions++;
6203 in->standby = 0;
6204 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006205 pthread_mutex_unlock(&in->lock);
6206 return bytes;
6207 }
6208
Haynes Mathew George16081042017-05-31 17:16:49 -07006209 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6210 ret = -ENOSYS;
6211 goto exit;
6212 }
6213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006214 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006215 pthread_mutex_lock(&adev->lock);
6216 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6217 ret = voice_extn_compress_voip_start_input_stream(in);
6218 else
6219 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006220 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6221 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006222 pthread_mutex_unlock(&adev->lock);
6223 if (ret != 0) {
6224 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006225 }
6226 in->standby = 0;
6227 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006228
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006229 // what's the duration requested by the client?
6230 long ns = 0;
6231
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306232 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006233 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6234 in->config.rate;
6235
6236 request_in_focus(in, ns);
6237 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006238
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306239 if (audio_extn_cin_attached_usecase(in->usecase)) {
6240 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6241 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306242 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006243 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306244 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006245 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006246 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006247 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006248 } else if (audio_extn_ffv_get_stream() == in) {
6249 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306250 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006251 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306252 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6253 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6254 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6255 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306256 ret = -EINVAL;
6257 goto exit;
6258 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306259 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306260 ret = -errno;
6261 }
6262 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306263 /* bytes read is always set to bytes for non compress usecases */
6264 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006265 }
6266
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006267 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006268
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006269 /*
Quinn Malef6050362019-01-30 15:55:40 -08006270 * Instead of writing zeroes here, we could trust the hardware to always
6271 * provide zeroes when muted. This is also muted with voice recognition
6272 * usecases so that other clients do not have access to voice recognition
6273 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006274 */
Quinn Malef6050362019-01-30 15:55:40 -08006275 if ((ret == 0 && voice_get_mic_mute(adev) &&
6276 !voice_is_in_call_rec_stream(in) &&
6277 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6278 (adev->num_va_sessions &&
6279 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6280 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6281 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006282 memset(buffer, 0, bytes);
6283
6284exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006285 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306286 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006287 pthread_mutex_unlock(&in->lock);
6288
6289 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306290 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306291 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306292 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306293 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306294 in->standby = true;
6295 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306296 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6297 bytes_read = bytes;
6298 memset(buffer, 0, bytes);
6299 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006300 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006301 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306302 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306303 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006304 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306305 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006306}
6307
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006308static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006309{
6310 return 0;
6311}
6312
Aalique Grahame22e49102018-12-18 14:23:57 -08006313static int in_get_capture_position(const struct audio_stream_in *stream,
6314 int64_t *frames, int64_t *time)
6315{
6316 if (stream == NULL || frames == NULL || time == NULL) {
6317 return -EINVAL;
6318 }
6319 struct stream_in *in = (struct stream_in *)stream;
6320 int ret = -ENOSYS;
6321
6322 lock_input_stream(in);
6323 // note: ST sessions do not close the alsa pcm driver synchronously
6324 // on standby. Therefore, we may return an error even though the
6325 // pcm stream is still opened.
6326 if (in->standby) {
6327 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6328 "%s stream in standby but pcm not NULL for non ST session", __func__);
6329 goto exit;
6330 }
6331 if (in->pcm) {
6332 struct timespec timestamp;
6333 unsigned int avail;
6334 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6335 *frames = in->frames_read + avail;
6336 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6337 ret = 0;
6338 }
6339 }
6340exit:
6341 pthread_mutex_unlock(&in->lock);
6342 return ret;
6343}
6344
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006345static int add_remove_audio_effect(const struct audio_stream *stream,
6346 effect_handle_t effect,
6347 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006348{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006349 struct stream_in *in = (struct stream_in *)stream;
6350 int status = 0;
6351 effect_descriptor_t desc;
6352
6353 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006354 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6355
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006356 if (status != 0)
6357 return status;
6358
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006359 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006360 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006361 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Aalique Grahame22e49102018-12-18 14:23:57 -08006362 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08006363 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006364 in->enable_aec != enable &&
6365 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
6366 in->enable_aec = enable;
Aalique Grahame22e49102018-12-18 14:23:57 -08006367 if (!enable)
6368 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
6369 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6370 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6371 in->dev->enable_voicerx = enable;
6372 struct audio_usecase *usecase;
6373 struct listnode *node;
6374 list_for_each(node, &in->dev->usecase_list) {
6375 usecase = node_to_item(node, struct audio_usecase, list);
6376 if (usecase->type == PCM_PLAYBACK)
6377 select_devices(in->dev, usecase->id);
6378 }
6379 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006380 if (!in->standby) {
6381 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6382 select_devices(in->dev, in->usecase);
6383 }
6384
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006385 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006386 if (in->enable_ns != enable &&
6387 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
6388 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006389 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006390 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6391 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006392 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6393 select_devices(in->dev, in->usecase);
6394 } else
6395 select_devices(in->dev, in->usecase);
6396 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006397 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006398 pthread_mutex_unlock(&in->dev->lock);
6399 pthread_mutex_unlock(&in->lock);
6400
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006401 return 0;
6402}
6403
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006404static int in_add_audio_effect(const struct audio_stream *stream,
6405 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006406{
Eric Laurent994a6932013-07-17 11:51:42 -07006407 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006408 return add_remove_audio_effect(stream, effect, true);
6409}
6410
6411static int in_remove_audio_effect(const struct audio_stream *stream,
6412 effect_handle_t effect)
6413{
Eric Laurent994a6932013-07-17 11:51:42 -07006414 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006415 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006416}
6417
Derek Chenf939fb72018-11-13 13:34:41 -08006418streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6419 audio_io_handle_t input)
6420{
6421 struct listnode *node;
6422
6423 list_for_each(node, &dev->active_inputs_list) {
6424 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6425 streams_input_ctxt_t,
6426 list);
6427 if (in_ctxt->input->capture_handle == input) {
6428 return in_ctxt;
6429 }
6430 }
6431 return NULL;
6432}
6433
6434streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6435 audio_io_handle_t output)
6436{
6437 struct listnode *node;
6438
6439 list_for_each(node, &dev->active_outputs_list) {
6440 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6441 streams_output_ctxt_t,
6442 list);
6443 if (out_ctxt->output->handle == output) {
6444 return out_ctxt;
6445 }
6446 }
6447 return NULL;
6448}
6449
Haynes Mathew George16081042017-05-31 17:16:49 -07006450static int in_stop(const struct audio_stream_in* stream)
6451{
6452 struct stream_in *in = (struct stream_in *)stream;
6453 struct audio_device *adev = in->dev;
6454
6455 int ret = -ENOSYS;
6456 ALOGV("%s", __func__);
6457 pthread_mutex_lock(&adev->lock);
6458 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6459 in->capture_started && in->pcm != NULL) {
6460 pcm_stop(in->pcm);
6461 ret = stop_input_stream(in);
6462 in->capture_started = false;
6463 }
6464 pthread_mutex_unlock(&adev->lock);
6465 return ret;
6466}
6467
6468static int in_start(const struct audio_stream_in* stream)
6469{
6470 struct stream_in *in = (struct stream_in *)stream;
6471 struct audio_device *adev = in->dev;
6472 int ret = -ENOSYS;
6473
6474 ALOGV("%s in %p", __func__, in);
6475 pthread_mutex_lock(&adev->lock);
6476 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6477 !in->capture_started && in->pcm != NULL) {
6478 if (!in->capture_started) {
6479 ret = start_input_stream(in);
6480 if (ret == 0) {
6481 in->capture_started = true;
6482 }
6483 }
6484 }
6485 pthread_mutex_unlock(&adev->lock);
6486 return ret;
6487}
6488
6489static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6490 int32_t min_size_frames,
6491 struct audio_mmap_buffer_info *info)
6492{
6493 struct stream_in *in = (struct stream_in *)stream;
6494 struct audio_device *adev = in->dev;
6495 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006496 unsigned int offset1 = 0;
6497 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006498 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006499 uint32_t mmap_size = 0;
6500 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006501
6502 pthread_mutex_lock(&adev->lock);
6503 ALOGV("%s in %p", __func__, in);
6504
Sharad Sanglec6f32552018-05-04 16:15:38 +05306505 if (CARD_STATUS_OFFLINE == in->card_status||
6506 CARD_STATUS_OFFLINE == adev->card_status) {
6507 ALOGW("in->card_status or adev->card_status offline, try again");
6508 ret = -EIO;
6509 goto exit;
6510 }
6511
Haynes Mathew George16081042017-05-31 17:16:49 -07006512 if (info == NULL || min_size_frames == 0) {
6513 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6514 ret = -EINVAL;
6515 goto exit;
6516 }
6517 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6518 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6519 ALOGV("%s in %p", __func__, in);
6520 ret = -ENOSYS;
6521 goto exit;
6522 }
6523 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6524 if (in->pcm_device_id < 0) {
6525 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6526 __func__, in->pcm_device_id, in->usecase);
6527 ret = -EINVAL;
6528 goto exit;
6529 }
6530
6531 adjust_mmap_period_count(&in->config, min_size_frames);
6532
6533 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
6534 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
6535 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6536 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306537 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306538 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6539 in->card_status = CARD_STATUS_OFFLINE;
6540 adev->card_status = CARD_STATUS_OFFLINE;
6541 ret = -EIO;
6542 goto exit;
6543 }
6544
Haynes Mathew George16081042017-05-31 17:16:49 -07006545 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6546 step = "open";
6547 ret = -ENODEV;
6548 goto exit;
6549 }
6550
6551 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6552 if (ret < 0) {
6553 step = "begin";
6554 goto exit;
6555 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006556
Arun Mirpuri5d170872019-03-26 13:21:31 -07006557 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
6558 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
6559 info->burst_size_frames = in->config.period_size;
6560 ret = platform_get_mmap_data_fd(adev->platform,
6561 in->pcm_device_id, 1 /*capture*/,
6562 &info->shared_memory_fd,
6563 &mmap_size);
6564 if (ret < 0) {
6565 // Fall back to non exclusive mode
6566 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6567 } else {
6568 if (mmap_size < buffer_size) {
6569 step = "mmap";
6570 goto exit;
6571 }
6572 // FIXME: indicate exclusive mode support by returning a negative buffer size
6573 info->buffer_size_frames *= -1;
6574 }
6575
6576 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006577
6578 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6579 if (ret < 0) {
6580 step = "commit";
6581 goto exit;
6582 }
6583
6584 in->standby = false;
6585 ret = 0;
6586
6587 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6588 __func__, info->shared_memory_address, info->buffer_size_frames);
6589
6590exit:
6591 if (ret != 0) {
6592 if (in->pcm == NULL) {
6593 ALOGE("%s: %s - %d", __func__, step, ret);
6594 } else {
6595 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6596 pcm_close(in->pcm);
6597 in->pcm = NULL;
6598 }
6599 }
6600 pthread_mutex_unlock(&adev->lock);
6601 return ret;
6602}
6603
6604static int in_get_mmap_position(const struct audio_stream_in *stream,
6605 struct audio_mmap_position *position)
6606{
6607 struct stream_in *in = (struct stream_in *)stream;
6608 ALOGVV("%s", __func__);
6609 if (position == NULL) {
6610 return -EINVAL;
6611 }
6612 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6613 return -ENOSYS;
6614 }
6615 if (in->pcm == NULL) {
6616 return -ENOSYS;
6617 }
6618 struct timespec ts = { 0, 0 };
6619 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6620 if (ret < 0) {
6621 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6622 return ret;
6623 }
Naresh Tanniru119d74a2018-11-02 09:49:44 +05306624 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07006625 return 0;
6626}
6627
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306628static int in_get_active_microphones(const struct audio_stream_in *stream,
6629 struct audio_microphone_characteristic_t *mic_array,
6630 size_t *mic_count) {
6631 struct stream_in *in = (struct stream_in *)stream;
6632 struct audio_device *adev = in->dev;
6633 ALOGVV("%s", __func__);
6634
6635 lock_input_stream(in);
6636 pthread_mutex_lock(&adev->lock);
6637 int ret = platform_get_active_microphones(adev->platform,
6638 audio_channel_count_from_in_mask(in->channel_mask),
6639 in->usecase, mic_array, mic_count);
6640 pthread_mutex_unlock(&adev->lock);
6641 pthread_mutex_unlock(&in->lock);
6642
6643 return ret;
6644}
6645
6646static int adev_get_microphones(const struct audio_hw_device *dev,
6647 struct audio_microphone_characteristic_t *mic_array,
6648 size_t *mic_count) {
6649 struct audio_device *adev = (struct audio_device *)dev;
6650 ALOGVV("%s", __func__);
6651
6652 pthread_mutex_lock(&adev->lock);
6653 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6654 pthread_mutex_unlock(&adev->lock);
6655
6656 return ret;
6657}
juyuchendb308c22019-01-21 11:57:17 -07006658
6659static void in_update_sink_metadata(struct audio_stream_in *stream,
6660 const struct sink_metadata *sink_metadata) {
6661
6662 if (stream == NULL
6663 || sink_metadata == NULL
6664 || sink_metadata->tracks == NULL) {
6665 return;
6666 }
6667
6668 int error = 0;
6669 struct stream_in *in = (struct stream_in *)stream;
6670 struct audio_device *adev = in->dev;
6671 audio_devices_t device = AUDIO_DEVICE_NONE;
6672
6673 if (sink_metadata->track_count != 0)
6674 device = sink_metadata->tracks->dest_device;
6675
6676 lock_input_stream(in);
6677 pthread_mutex_lock(&adev->lock);
6678 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
6679
6680 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
6681 && device != AUDIO_DEVICE_NONE
6682 && adev->voice_tx_output != NULL) {
6683 /* Use the rx device from afe-proxy record to route voice call because
6684 there is no routing if tx device is on primary hal and rx device
6685 is on other hal during voice call. */
6686 adev->voice_tx_output->devices = device;
6687
6688 if (!voice_is_call_state_active(adev)) {
6689 if (adev->mode == AUDIO_MODE_IN_CALL) {
6690 adev->current_call_output = adev->voice_tx_output;
6691 error = voice_start_call(adev);
6692 if (error != 0)
6693 ALOGE("%s: start voice call failed %d", __func__, error);
6694 }
6695 } else {
6696 adev->current_call_output = adev->voice_tx_output;
6697 voice_update_devices_for_all_voice_usecases(adev);
6698 }
6699 }
6700
6701 pthread_mutex_unlock(&adev->lock);
6702 pthread_mutex_unlock(&in->lock);
6703}
6704
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306705int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006706 audio_io_handle_t handle,
6707 audio_devices_t devices,
6708 audio_output_flags_t flags,
6709 struct audio_config *config,
6710 struct audio_stream_out **stream_out,
6711 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006712{
6713 struct audio_device *adev = (struct audio_device *)dev;
6714 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05306715 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006716 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006717 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306718 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006719 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6720 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6721 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6722 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006723 bool use_db_as_primary =
Aalique Grahame6e763712019-01-31 16:18:17 -08006724 audio_feature_manager_is_feature_enabled(USE_DEEP_BUFFER_AS_PRIMARY_OUTPUT);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006725 bool force_haptic_path =
6726 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07006727 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006728
kunleizdff872d2018-08-20 14:40:33 +08006729 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006730 is_usb_dev = false;
6731 devices = AUDIO_DEVICE_OUT_SPEAKER;
6732 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6733 __func__, devices);
6734 }
6735
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006736 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306737
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006738 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6739
Mingming Yin3a941d42016-02-17 18:08:05 -08006740 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6741 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306742 devices, flags, &out->stream);
6743
6744
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006745 if (!out) {
6746 return -ENOMEM;
6747 }
6748
Haynes Mathew George204045b2015-02-25 20:32:03 -08006749 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006750 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306751 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006752 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006753 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6754
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006755 if (devices == AUDIO_DEVICE_NONE)
6756 devices = AUDIO_DEVICE_OUT_SPEAKER;
6757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006758 out->flags = flags;
6759 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006760 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006761 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006762 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306763 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306764 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6765 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6766 else
6767 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006768 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006769 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006770 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306771 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306772 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306773 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006774 out->hal_output_suspend_supported = 0;
6775 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05306776 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306777 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306778 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006779
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306780 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306781 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006782 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6783
Aalique Grahame22e49102018-12-18 14:23:57 -08006784 if (direct_dev &&
6785 (audio_is_linear_pcm(out->format) ||
6786 config->format == AUDIO_FORMAT_DEFAULT) &&
6787 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
6788 audio_format_t req_format = config->format;
6789 audio_channel_mask_t req_channel_mask = config->channel_mask;
6790 uint32_t req_sample_rate = config->sample_rate;
6791
6792 pthread_mutex_lock(&adev->lock);
6793 if (is_hdmi) {
6794 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6795 ret = read_hdmi_sink_caps(out);
6796 if (config->sample_rate == 0)
6797 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6798 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6799 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
6800 if (config->format == AUDIO_FORMAT_DEFAULT)
6801 config->format = AUDIO_FORMAT_PCM_16_BIT;
6802 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006803 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6804 &config->format,
6805 &out->supported_formats[0],
6806 MAX_SUPPORTED_FORMATS,
6807 &config->channel_mask,
6808 &out->supported_channel_masks[0],
6809 MAX_SUPPORTED_CHANNEL_MASKS,
6810 &config->sample_rate,
6811 &out->supported_sample_rates[0],
6812 MAX_SUPPORTED_SAMPLE_RATES);
6813 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006814 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006815
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006816 pthread_mutex_unlock(&adev->lock);
6817 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006818 if (ret == -ENOSYS) {
6819 /* ignore and go with default */
6820 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08006821 }
6822 // For MMAP NO IRQ, allow conversions in ADSP
6823 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
6824 goto error_open;
6825 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006826 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006827 goto error_open;
6828 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006829
6830 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
6831 config->sample_rate = req_sample_rate;
6832 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
6833 config->channel_mask = req_channel_mask;
6834 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
6835 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08006836 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006837
6838 out->sample_rate = config->sample_rate;
6839 out->channel_mask = config->channel_mask;
6840 out->format = config->format;
6841 if (is_hdmi) {
6842 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6843 out->config = pcm_config_hdmi_multi;
6844 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6845 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6846 out->config = pcm_config_mmap_playback;
6847 out->stream.start = out_start;
6848 out->stream.stop = out_stop;
6849 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6850 out->stream.get_mmap_position = out_get_mmap_position;
6851 } else {
6852 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6853 out->config = pcm_config_hifi;
6854 }
6855
6856 out->config.rate = out->sample_rate;
6857 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6858 if (is_hdmi) {
6859 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6860 audio_bytes_per_sample(out->format));
6861 }
6862 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08006863 }
6864
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006865 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07006866 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006867 if (!voice_extn_is_compress_voip_supported()) {
6868 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6869 out->sample_rate == 32000 || out->sample_rate == 48000) {
kunleizf6b5b082019-03-18 17:32:25 +08006870 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006871 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
6872 out->format = AUDIO_FORMAT_PCM_16_BIT;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006873
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006874 out->config = default_pcm_config_voip_copp;
6875 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6876 out->config.rate = out->sample_rate;
6877 }
6878 } else {
6879 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6880 voice_extn_compress_voip_is_active(out->dev)) &&
6881 (voice_extn_compress_voip_is_config_supported(config))) {
6882 ret = voice_extn_compress_voip_open_output_stream(out);
6883 if (ret != 0) {
6884 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6885 __func__, ret);
6886 goto error_open;
6887 }
6888 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006889 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006890 } else if (audio_is_linear_pcm(out->format) &&
6891 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6892 out->channel_mask = config->channel_mask;
6893 out->sample_rate = config->sample_rate;
6894 out->format = config->format;
6895 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6896 // does this change?
6897 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6898 out->config.rate = config->sample_rate;
6899 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6900 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6901 audio_bytes_per_sample(config->format));
6902 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006903 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306904 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306905 pthread_mutex_lock(&adev->lock);
6906 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6907 pthread_mutex_unlock(&adev->lock);
6908
6909 // reject offload during card offline to allow
6910 // fallback to s/w paths
6911 if (offline) {
6912 ret = -ENODEV;
6913 goto error_open;
6914 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006915
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006916 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6917 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6918 ALOGE("%s: Unsupported Offload information", __func__);
6919 ret = -EINVAL;
6920 goto error_open;
6921 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006922
Atul Khare3fa6e542017-08-09 00:56:17 +05306923 if (config->offload_info.format == 0)
6924 config->offload_info.format = config->format;
6925 if (config->offload_info.sample_rate == 0)
6926 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006927
Mingming Yin90310102013-11-13 16:57:00 -08006928 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306929 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006930 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006931 ret = -EINVAL;
6932 goto error_open;
6933 }
6934
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006935 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6936 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6937 (audio_extn_passthru_is_passthrough_stream(out)) &&
6938 !((config->sample_rate == 48000) ||
6939 (config->sample_rate == 96000) ||
6940 (config->sample_rate == 192000))) {
6941 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6942 __func__, config->sample_rate, config->offload_info.format);
6943 ret = -EINVAL;
6944 goto error_open;
6945 }
6946
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006947 out->compr_config.codec = (struct snd_codec *)
6948 calloc(1, sizeof(struct snd_codec));
6949
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006950 if (!out->compr_config.codec) {
6951 ret = -ENOMEM;
6952 goto error_open;
6953 }
6954
Dhananjay Kumarac341582017-02-23 23:42:25 +05306955 out->stream.pause = out_pause;
6956 out->stream.resume = out_resume;
6957 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306958 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306959 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006960 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306961 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006962 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306963 } else {
6964 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6965 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006966 }
vivek mehta446c3962015-09-14 10:57:35 -07006967
6968 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006969 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6970 config->format == 0 && config->sample_rate == 0 &&
6971 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006972 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006973 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6974 } else {
6975 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6976 ret = -EEXIST;
6977 goto error_open;
6978 }
vivek mehta446c3962015-09-14 10:57:35 -07006979 }
6980
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006981 if (config->offload_info.channel_mask)
6982 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006983 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006984 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006985 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006986 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306987 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006988 ret = -EINVAL;
6989 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006990 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006991
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006992 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006993 out->sample_rate = config->offload_info.sample_rate;
6994
Mingming Yin3ee55c62014-08-04 14:23:35 -07006995 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006996
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306997 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306998 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306999 audio_extn_dolby_send_ddp_endp_params(adev);
7000 audio_extn_dolby_set_dmid(adev);
7001 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007002
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007003 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007004 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007005 out->compr_config.codec->bit_rate =
7006 config->offload_info.bit_rate;
7007 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307008 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007009 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307010 /* Update bit width only for non passthrough usecases.
7011 * For passthrough usecases, the output will always be opened @16 bit
7012 */
7013 if (!audio_extn_passthru_is_passthrough_stream(out))
7014 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307015
7016 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
7017 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7018 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
7019
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007020 /*TODO: Do we need to change it for passthrough */
7021 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007022
Manish Dewangana6fc5442015-08-24 20:30:31 +05307023 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7024 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307025 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307026 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307027 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7028 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307029
7030 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7031 AUDIO_FORMAT_PCM) {
7032
7033 /*Based on platform support, configure appropriate alsa format for corresponding
7034 *hal input format.
7035 */
7036 out->compr_config.codec->format = hal_format_to_alsa(
7037 config->offload_info.format);
7038
Ashish Jain83a6cc22016-06-28 14:34:17 +05307039 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307040 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307041 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307042
Dhananjay Kumarac341582017-02-23 23:42:25 +05307043 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307044 *hal input format and alsa format might differ based on platform support.
7045 */
7046 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307047 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307048
7049 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7050
7051 /* Check if alsa session is configured with the same format as HAL input format,
7052 * if not then derive correct fragment size needed to accomodate the
7053 * conversion of HAL input format to alsa format.
7054 */
7055 audio_extn_utils_update_direct_pcm_fragment_size(out);
7056
7057 /*if hal input and output fragment size is different this indicates HAL input format is
7058 *not same as the alsa format
7059 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307060 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307061 /*Allocate a buffer to convert input data to the alsa configured format.
7062 *size of convert buffer is equal to the size required to hold one fragment size
7063 *worth of pcm data, this is because flinger does not write more than fragment_size
7064 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307065 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7066 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307067 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7068 ret = -ENOMEM;
7069 goto error_open;
7070 }
7071 }
7072 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7073 out->compr_config.fragment_size =
7074 audio_extn_passthru_get_buffer_size(&config->offload_info);
7075 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7076 } else {
7077 out->compr_config.fragment_size =
7078 platform_get_compress_offload_buffer_size(&config->offload_info);
7079 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7080 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007081
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307082 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7083 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7084 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007085 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307086 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007087
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307088 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7089 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7090 }
7091
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007092 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7093 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007094
Manish Dewangan69426c82017-01-30 17:35:36 +05307095 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7096 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7097 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7098 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7099 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7100 } else {
7101 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7102 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007103
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307104 memset(&out->channel_map_param, 0,
7105 sizeof(struct audio_out_channel_map_param));
7106
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007107 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307108 out->send_next_track_params = false;
7109 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007110 out->offload_state = OFFLOAD_STATE_IDLE;
7111 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007112 out->writeAt.tv_sec = 0;
7113 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007114
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007115 audio_extn_dts_create_state_notifier_node(out->usecase);
7116
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007117 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7118 __func__, config->offload_info.version,
7119 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307120
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307121 /* Check if DSD audio format is supported in codec
7122 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307123 */
7124
7125 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307126 (!platform_check_codec_dsd_support(adev->platform) ||
7127 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307128 ret = -EINVAL;
7129 goto error_open;
7130 }
7131
Ashish Jain5106d362016-05-11 19:23:33 +05307132 /* Disable gapless if any of the following is true
7133 * passthrough playback
7134 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307135 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307136 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307137 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307138 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007139 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307140 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307141 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307142 check_and_set_gapless_mode(adev, false);
7143 } else
7144 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007145
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307146 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007147 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7148 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307149 if (config->format == AUDIO_FORMAT_DSD) {
7150 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7151 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
7152 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007153
7154 create_offload_callback_thread(out);
7155
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007156 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007157 switch (config->sample_rate) {
7158 case 0:
7159 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7160 break;
7161 case 8000:
7162 case 16000:
7163 case 48000:
7164 out->sample_rate = config->sample_rate;
7165 break;
7166 default:
7167 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7168 config->sample_rate);
7169 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7170 ret = -EINVAL;
7171 goto error_open;
7172 }
7173 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7174 switch (config->channel_mask) {
7175 case AUDIO_CHANNEL_NONE:
7176 case AUDIO_CHANNEL_OUT_STEREO:
7177 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7178 break;
7179 default:
7180 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7181 config->channel_mask);
7182 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7183 ret = -EINVAL;
7184 goto error_open;
7185 }
7186 switch (config->format) {
7187 case AUDIO_FORMAT_DEFAULT:
7188 case AUDIO_FORMAT_PCM_16_BIT:
7189 out->format = AUDIO_FORMAT_PCM_16_BIT;
7190 break;
7191 default:
7192 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7193 config->format);
7194 config->format = AUDIO_FORMAT_PCM_16_BIT;
7195 ret = -EINVAL;
7196 goto error_open;
7197 }
7198
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307199 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007200 if (ret != 0) {
7201 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007202 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007203 goto error_open;
7204 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007205 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007206 switch (config->sample_rate) {
7207 case 0:
7208 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7209 break;
7210 case 8000:
7211 case 16000:
7212 case 48000:
7213 out->sample_rate = config->sample_rate;
7214 break;
7215 default:
7216 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7217 config->sample_rate);
7218 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7219 ret = -EINVAL;
7220 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007221 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007222 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7223 switch (config->channel_mask) {
7224 case AUDIO_CHANNEL_NONE:
7225 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7226 break;
7227 case AUDIO_CHANNEL_OUT_STEREO:
7228 out->channel_mask = config->channel_mask;
7229 break;
7230 default:
7231 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7232 config->channel_mask);
7233 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7234 ret = -EINVAL;
7235 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007236 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007237 switch (config->format) {
7238 case AUDIO_FORMAT_DEFAULT:
7239 out->format = AUDIO_FORMAT_PCM_16_BIT;
7240 break;
7241 case AUDIO_FORMAT_PCM_16_BIT:
7242 out->format = config->format;
7243 break;
7244 default:
7245 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7246 config->format);
7247 config->format = AUDIO_FORMAT_PCM_16_BIT;
7248 ret = -EINVAL;
7249 break;
7250 }
7251 if (ret != 0)
7252 goto error_open;
7253
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007254 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7255 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007256 out->config.rate = out->sample_rate;
7257 out->config.channels =
7258 audio_channel_count_from_out_mask(out->channel_mask);
7259 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007260 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007261 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307262 unsigned int channels = 0;
7263 /*Update config params to default if not set by the caller*/
7264 if (config->sample_rate == 0)
7265 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7266 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7267 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7268 if (config->format == AUDIO_FORMAT_DEFAULT)
7269 config->format = AUDIO_FORMAT_PCM_16_BIT;
7270
7271 channels = audio_channel_count_from_out_mask(out->channel_mask);
7272
Varun Balaraje49253e2017-07-06 19:48:56 +05307273 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7274 out->usecase = get_interactive_usecase(adev);
7275 out->config = pcm_config_low_latency;
7276 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307277 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007278 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7279 out->flags);
7280 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007281 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7282 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7283 out->config = pcm_config_mmap_playback;
7284 out->stream.start = out_start;
7285 out->stream.stop = out_stop;
7286 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7287 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307288 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7289 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007290 out->hal_output_suspend_supported =
7291 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7292 out->dynamic_pm_qos_config_supported =
7293 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7294 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007295 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7296 } else {
7297 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7298 //the mixer path will be a string similar to "low-latency-playback resume"
7299 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7300 strlcat(out->pm_qos_mixer_path,
7301 " resume", MAX_MIXER_PATH_LEN);
7302 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7303 out->pm_qos_mixer_path);
7304 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307305 out->config = pcm_config_low_latency;
7306 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7307 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7308 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307309 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7310 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7311 if (out->config.period_size <= 0) {
7312 ALOGE("Invalid configuration period size is not valid");
7313 ret = -EINVAL;
7314 goto error_open;
7315 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007316 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7317 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7318 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007319 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7320 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7321 out->config = pcm_config_haptics_audio;
7322 if (force_haptic_path)
7323 adev->haptics_config = pcm_config_haptics_audio;
7324 else
7325 adev->haptics_config = pcm_config_haptics;
7326
7327 out->config.channels =
7328 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7329
7330 if (force_haptic_path) {
7331 out->config.channels = 1;
7332 adev->haptics_config.channels = 1;
7333 } else
7334 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307335 } else {
7336 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007337 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7338 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307339 }
7340 out->hal_ip_format = format = out->format;
7341 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7342 out->hal_op_format = pcm_format_to_hal(out->config.format);
7343 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7344 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007345 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307346 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307347 if (out->hal_ip_format != out->hal_op_format) {
7348 uint32_t buffer_size = out->config.period_size *
7349 format_to_bitwidth_table[out->hal_op_format] *
7350 out->config.channels;
7351 out->convert_buffer = calloc(1, buffer_size);
7352 if (out->convert_buffer == NULL){
7353 ALOGE("Allocation failed for convert buffer for size %d",
7354 out->compr_config.fragment_size);
7355 ret = -ENOMEM;
7356 goto error_open;
7357 }
7358 ALOGD("Convert buffer allocated of size %d", buffer_size);
7359 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007360 }
7361
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007362 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7363 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307364
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007365 /* TODO remove this hardcoding and check why width is zero*/
7366 if (out->bit_width == 0)
7367 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307368 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007369 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007370 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307371 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307372 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007373 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007374 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7375 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007376 if(adev->primary_output == NULL)
7377 adev->primary_output = out;
7378 else {
7379 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007380 ret = -EEXIST;
7381 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007382 }
7383 }
7384
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007385 /* Check if this usecase is already existing */
7386 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007387 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7388 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007389 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007390 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007391 ret = -EEXIST;
7392 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007393 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007394
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007395 pthread_mutex_unlock(&adev->lock);
7396
7397 out->stream.common.get_sample_rate = out_get_sample_rate;
7398 out->stream.common.set_sample_rate = out_set_sample_rate;
7399 out->stream.common.get_buffer_size = out_get_buffer_size;
7400 out->stream.common.get_channels = out_get_channels;
7401 out->stream.common.get_format = out_get_format;
7402 out->stream.common.set_format = out_set_format;
7403 out->stream.common.standby = out_standby;
7404 out->stream.common.dump = out_dump;
7405 out->stream.common.set_parameters = out_set_parameters;
7406 out->stream.common.get_parameters = out_get_parameters;
7407 out->stream.common.add_audio_effect = out_add_audio_effect;
7408 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7409 out->stream.get_latency = out_get_latency;
7410 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007411#ifdef NO_AUDIO_OUT
7412 out->stream.write = out_write_for_no_output;
7413#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007414 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007415#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007416 out->stream.get_render_position = out_get_render_position;
7417 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007418 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007419
Haynes Mathew George16081042017-05-31 17:16:49 -07007420 if (out->realtime)
7421 out->af_period_multiplier = af_period_multiplier;
7422 else
7423 out->af_period_multiplier = 1;
7424
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007425 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007426 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007427 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007428
7429 config->format = out->stream.common.get_format(&out->stream.common);
7430 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7431 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307432 register_format(out->format, out->supported_formats);
7433 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7434 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007435
Aalique Grahame22e49102018-12-18 14:23:57 -08007436 out->error_log = error_log_create(
7437 ERROR_LOG_ENTRIES,
7438 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7439
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307440 /*
7441 By locking output stream before registering, we allow the callback
7442 to update stream's state only after stream's initial state is set to
7443 adev state.
7444 */
7445 lock_output_stream(out);
7446 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7447 pthread_mutex_lock(&adev->lock);
7448 out->card_status = adev->card_status;
7449 pthread_mutex_unlock(&adev->lock);
7450 pthread_mutex_unlock(&out->lock);
7451
Aalique Grahame22e49102018-12-18 14:23:57 -08007452 stream_app_type_cfg_init(&out->app_type_cfg);
7453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007454 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307455 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007456 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007457
7458 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7459 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7460 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007461 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307462 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007463 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007464 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05307465 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
7466 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007467 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
7468 out->usecase, PCM_PLAYBACK);
7469 hdlr_stream_cfg.flags = out->flags;
7470 hdlr_stream_cfg.type = PCM_PLAYBACK;
7471 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
7472 &hdlr_stream_cfg);
7473 if (ret) {
7474 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
7475 out->adsp_hdlr_stream_handle = NULL;
7476 }
7477 }
Gangadhar Sb0210342019-02-22 17:39:41 +05307478 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
7479 is_direct_passthough, false);
7480 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
7481 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07007482 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07007483 if (ret < 0) {
7484 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
7485 out->ip_hdlr_handle = NULL;
7486 }
7487 }
Derek Chenf939fb72018-11-13 13:34:41 -08007488
7489 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
7490 calloc(1, sizeof(streams_output_ctxt_t));
7491 if (out_ctxt == NULL) {
7492 ALOGE("%s fail to allocate output ctxt", __func__);
7493 ret = -ENOMEM;
7494 goto error_open;
7495 }
7496 out_ctxt->output = out;
7497
7498 pthread_mutex_lock(&adev->lock);
7499 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
7500 pthread_mutex_unlock(&adev->lock);
7501
Eric Laurent994a6932013-07-17 11:51:42 -07007502 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007503 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007504
7505error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05307506 if (out->convert_buffer)
7507 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007508 free(out);
7509 *stream_out = NULL;
7510 ALOGD("%s: exit: ret %d", __func__, ret);
7511 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007512}
7513
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307514void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007515 struct audio_stream_out *stream)
7516{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007517 struct stream_out *out = (struct stream_out *)stream;
7518 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007519 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007520
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007521 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307522
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307523 // must deregister from sndmonitor first to prevent races
7524 // between the callback and close_stream
7525 audio_extn_snd_mon_unregister_listener(out);
7526
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007527 /* close adsp hdrl session before standby */
7528 if (out->adsp_hdlr_stream_handle) {
7529 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
7530 if (ret)
7531 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
7532 out->adsp_hdlr_stream_handle = NULL;
7533 }
7534
Manish Dewangan21a850a2017-08-14 12:03:55 +05307535 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07007536 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
7537 out->ip_hdlr_handle = NULL;
7538 }
7539
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007540 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307541 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007542 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307543 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307544 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007545 if(ret != 0)
7546 ALOGE("%s: Compress voip output cannot be closed, error:%d",
7547 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007548 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007549 out_standby(&stream->common);
7550
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007551 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007552 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007553 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007554 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007555 if (out->compr_config.codec != NULL)
7556 free(out->compr_config.codec);
7557 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007558
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307559 out->a2dp_compress_mute = false;
7560
Varun Balaraje49253e2017-07-06 19:48:56 +05307561 if (is_interactive_usecase(out->usecase))
7562 free_interactive_usecase(adev, out->usecase);
7563
Ashish Jain83a6cc22016-06-28 14:34:17 +05307564 if (out->convert_buffer != NULL) {
7565 free(out->convert_buffer);
7566 out->convert_buffer = NULL;
7567 }
7568
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007569 if (adev->voice_tx_output == out)
7570 adev->voice_tx_output = NULL;
7571
Aalique Grahame22e49102018-12-18 14:23:57 -08007572 error_log_destroy(out->error_log);
7573 out->error_log = NULL;
7574
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05307575 if (adev->primary_output == out)
7576 adev->primary_output = NULL;
7577
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007578 pthread_cond_destroy(&out->cond);
7579 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08007580
7581 pthread_mutex_lock(&adev->lock);
7582 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
7583 if (out_ctxt != NULL) {
7584 list_remove(&out_ctxt->list);
7585 free(out_ctxt);
7586 } else {
7587 ALOGW("%s, output stream already closed", __func__);
7588 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007589 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08007590 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007591 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007592}
7593
7594static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
7595{
7596 struct audio_device *adev = (struct audio_device *)dev;
7597 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007598 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007599 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007600 int ret;
7601 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007602 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007603
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007604 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007605 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007606
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307607 if (!parms)
7608 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307609
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307610 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
7611 if (ret >= 0) {
7612 /* When set to false, HAL should disable EC and NS */
7613 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7614 adev->bt_sco_on = true;
7615 else
7616 adev->bt_sco_on = false;
7617 }
7618
Naresh Tanniru4c630392014-05-12 01:05:52 +05307619 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007620 status = voice_set_parameters(adev, parms);
7621 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007622 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007623
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007624 status = platform_set_parameters(adev->platform, parms);
7625 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007626 goto done;
7627
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007628 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
7629 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07007630 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007631 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7632 adev->bluetooth_nrec = true;
7633 else
7634 adev->bluetooth_nrec = false;
7635 }
7636
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007637 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
7638 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007639 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7640 adev->screen_off = false;
7641 else
7642 adev->screen_off = true;
7643 }
7644
Arun Mirpurid750ac52019-04-12 18:33:55 -07007645 if(!audio_extn_is_maxx_audio_enabled()) {
7646 ret = str_parms_get_int(parms, "rotation", &val);
7647 if (ret >= 0) {
7648 bool reverse_speakers = false;
7649 switch(val) {
7650 // FIXME: note that the code below assumes that the speakers are
7651 // in the correct placement relative to the user when the device
7652 // is rotated 90deg from its default rotation. This assumption
7653 // is device-specific, not platform-specific like this code.
7654 case 270:
7655 reverse_speakers = true;
7656 break;
7657 case 0:
7658 case 90:
7659 case 180:
7660 break;
7661 default:
7662 ALOGE("%s: unexpected rotation of %d", __func__, val);
7663 status = -EINVAL;
7664 }
7665 if (status == 0) {
7666 // check and set swap
7667 // - check if orientation changed and speaker active
7668 // - set rotation and cache the rotation value
7669 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
7670 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007671 }
Arun Mirpurid750ac52019-04-12 18:33:55 -07007672 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007673
Mingming Yin514a8bc2014-07-29 15:22:21 -07007674 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
7675 if (ret >= 0) {
7676 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7677 adev->bt_wb_speech_enabled = true;
7678 else
7679 adev->bt_wb_speech_enabled = false;
7680 }
7681
Zhou Song12c29502019-03-16 10:37:18 +08007682 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
7683 if (ret >= 0) {
7684 val = atoi(value);
7685 adev->swb_speech_mode = val;
7686 }
7687
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007688 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
7689 if (ret >= 0) {
7690 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307691 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08007692 if (audio_is_output_device(val) &&
7693 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007694 ALOGV("cache new ext disp type and edid");
7695 ret = platform_get_ext_disp_type(adev->platform);
7696 if (ret < 0) {
7697 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05307698 } else {
7699 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007700 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307701 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07007702 /*
7703 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
7704 * Per AudioPolicyManager, USB device is higher priority than WFD.
7705 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
7706 * If WFD use case occupies AFE proxy, it may result unintended behavior while
7707 * starting voice call on USB
7708 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007709 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307710 if (ret >= 0)
7711 audio_extn_usb_add_device(device, atoi(value));
7712
Zhou Song6f862822017-11-06 17:27:57 +08007713 if (!audio_extn_usb_is_tunnel_supported()) {
7714 ALOGV("detected USB connect .. disable proxy");
7715 adev->allow_afe_proxy_usage = false;
7716 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007717 }
7718 }
7719
7720 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
7721 if (ret >= 0) {
7722 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307723 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07007724 /*
7725 * The HDMI / Displayport disconnect handling has been moved to
7726 * audio extension to ensure that its parameters are not
7727 * invalidated prior to updating sysfs of the disconnect event
7728 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
7729 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307730 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007731 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307732 if (ret >= 0)
7733 audio_extn_usb_remove_device(device, atoi(value));
7734
Zhou Song6f862822017-11-06 17:27:57 +08007735 if (!audio_extn_usb_is_tunnel_supported()) {
7736 ALOGV("detected USB disconnect .. enable proxy");
7737 adev->allow_afe_proxy_usage = true;
7738 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007739 }
7740 }
7741
Aalique Grahame22e49102018-12-18 14:23:57 -08007742 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007743 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08007744
7745 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08007746 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307747 struct audio_usecase *usecase;
7748 struct listnode *node;
7749 list_for_each(node, &adev->usecase_list) {
7750 usecase = node_to_item(node, struct audio_usecase, list);
7751 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07007752 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307753 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08007754
7755 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307756 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08007757 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307758 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307759 //force device switch to re configure encoder
7760 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307761 audio_extn_a2dp_set_handoff_mode(false);
7762 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307763 break;
7764 }
7765 }
7766 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007767
7768 //handle vr audio setparam
7769 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7770 value, sizeof(value));
7771 if (ret >= 0) {
7772 ALOGI("Setting vr mode to be %s", value);
7773 if (!strncmp(value, "true", 4)) {
7774 adev->vr_audio_mode_enabled = true;
7775 ALOGI("Setting vr mode to true");
7776 } else if (!strncmp(value, "false", 5)) {
7777 adev->vr_audio_mode_enabled = false;
7778 ALOGI("Setting vr mode to false");
7779 } else {
7780 ALOGI("wrong vr mode set");
7781 }
7782 }
7783
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307784 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007785done:
7786 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007787 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307788error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007789 ALOGV("%s: exit with code(%d)", __func__, status);
7790 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007791}
7792
7793static char* adev_get_parameters(const struct audio_hw_device *dev,
7794 const char *keys)
7795{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307796 ALOGD("%s:%s", __func__, keys);
7797
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007798 struct audio_device *adev = (struct audio_device *)dev;
7799 struct str_parms *reply = str_parms_create();
7800 struct str_parms *query = str_parms_create_str(keys);
7801 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05307802 char value[256] = {0};
7803 int ret = 0;
7804
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007805 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007806 if (reply) {
7807 str_parms_destroy(reply);
7808 }
7809 if (query) {
7810 str_parms_destroy(query);
7811 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007812 ALOGE("adev_get_parameters: failed to create query or reply");
7813 return NULL;
7814 }
7815
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007816 //handle vr audio getparam
7817
7818 ret = str_parms_get_str(query,
7819 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7820 value, sizeof(value));
7821
7822 if (ret >= 0) {
7823 bool vr_audio_enabled = false;
7824 pthread_mutex_lock(&adev->lock);
7825 vr_audio_enabled = adev->vr_audio_mode_enabled;
7826 pthread_mutex_unlock(&adev->lock);
7827
7828 ALOGI("getting vr mode to %d", vr_audio_enabled);
7829
7830 if (vr_audio_enabled) {
7831 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7832 "true");
7833 goto exit;
7834 } else {
7835 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7836 "false");
7837 goto exit;
7838 }
7839 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007840
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007841 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007842 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08007843 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08007844 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007845 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05307846 pthread_mutex_unlock(&adev->lock);
7847
Naresh Tannirud7205b62014-06-20 02:54:48 +05307848exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007849 str = str_parms_to_str(reply);
7850 str_parms_destroy(query);
7851 str_parms_destroy(reply);
7852
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307853 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007854 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007855}
7856
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007857static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007858{
7859 return 0;
7860}
7861
7862static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
7863{
Haynes Mathew George5191a852013-09-11 14:19:36 -07007864 int ret;
7865 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08007866
7867 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
7868
Haynes Mathew George5191a852013-09-11 14:19:36 -07007869 pthread_mutex_lock(&adev->lock);
7870 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07007871 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07007872 pthread_mutex_unlock(&adev->lock);
7873 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007874}
7875
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007876static int adev_set_master_volume(struct audio_hw_device *dev __unused,
7877 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007878{
7879 return -ENOSYS;
7880}
7881
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007882static int adev_get_master_volume(struct audio_hw_device *dev __unused,
7883 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007884{
7885 return -ENOSYS;
7886}
7887
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007888static int adev_set_master_mute(struct audio_hw_device *dev __unused,
7889 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007890{
7891 return -ENOSYS;
7892}
7893
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007894static int adev_get_master_mute(struct audio_hw_device *dev __unused,
7895 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007896{
7897 return -ENOSYS;
7898}
7899
7900static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
7901{
7902 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07007903 struct listnode *node;
7904 struct audio_usecase *usecase = NULL;
7905 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08007906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007907 pthread_mutex_lock(&adev->lock);
7908 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007909 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007910 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08007911 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07007912 list_for_each(node, &adev->usecase_list) {
7913 usecase = node_to_item(node, struct audio_usecase, list);
7914 if (usecase->type == VOICE_CALL)
7915 break;
7916 }
7917 if (usecase &&
7918 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
7919 ret = audio_extn_usb_check_and_set_svc_int(usecase,
7920 true);
7921 if (ret != 0) {
7922 /* default service interval was successfully updated,
7923 reopen USB backend with new service interval */
7924 check_usecases_codec_backend(adev,
7925 usecase,
7926 usecase->out_snd_device);
7927 }
7928 }
7929
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007930 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07007931 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007932 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08007933 // restore device for other active usecases after stop call
7934 list_for_each(node, &adev->usecase_list) {
7935 usecase = node_to_item(node, struct audio_usecase, list);
7936 select_devices(adev, usecase->id);
7937 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007938 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007939 }
7940 pthread_mutex_unlock(&adev->lock);
7941 return 0;
7942}
7943
7944static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
7945{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007946 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08007947 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007948
7949 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08007950 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007951 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007952
Derek Chend2530072014-11-24 12:39:14 -08007953 if (adev->ext_hw_plugin)
7954 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007955
7956 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007957 pthread_mutex_unlock(&adev->lock);
7958
7959 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007960}
7961
7962static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
7963{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007964 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007965 return 0;
7966}
7967
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007968static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007969 const struct audio_config *config)
7970{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007971 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007972
Aalique Grahame22e49102018-12-18 14:23:57 -08007973 /* Don't know if USB HIFI in this context so use true to be conservative */
7974 if (check_input_parameters(config->sample_rate, config->format, channel_count,
7975 true /*is_usb_hifi */) != 0)
7976 return 0;
7977
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007978 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
7979 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007980}
7981
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007982static bool adev_input_allow_hifi_record(struct audio_device *adev,
7983 audio_devices_t devices,
7984 audio_input_flags_t flags,
7985 audio_source_t source) {
7986 const bool allowed = true;
7987
7988 if (!audio_is_usb_in_device(devices))
7989 return !allowed;
7990
7991 switch (flags) {
7992 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007993 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07007994 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7995 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007996 default:
7997 return !allowed;
7998 }
7999
8000 switch (source) {
8001 case AUDIO_SOURCE_DEFAULT:
8002 case AUDIO_SOURCE_MIC:
8003 case AUDIO_SOURCE_UNPROCESSED:
8004 break;
8005 default:
8006 return !allowed;
8007 }
8008
8009 switch (adev->mode) {
8010 case 0:
8011 break;
8012 default:
8013 return !allowed;
8014 }
8015
8016 return allowed;
8017}
8018
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008019static int adev_update_voice_comm_input_stream(struct stream_in *in,
8020 struct audio_config *config)
8021{
8022 bool valid_rate = (config->sample_rate == 8000 ||
8023 config->sample_rate == 16000 ||
8024 config->sample_rate == 32000 ||
8025 config->sample_rate == 48000);
8026 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8027
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008028 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008029 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008030 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8031 in->config = default_pcm_config_voip_copp;
8032 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8033 DEFAULT_VOIP_BUF_DURATION_MS,
8034 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008035 } else {
8036 ALOGW("%s No valid input in voip, use defaults"
8037 "sample rate %u, channel mask 0x%X",
8038 __func__, config->sample_rate, in->channel_mask);
8039 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008040 in->config.rate = config->sample_rate;
8041 in->sample_rate = config->sample_rate;
8042 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008043 //XXX needed for voice_extn_compress_voip_open_input_stream
8044 in->config.rate = config->sample_rate;
8045 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8046 voice_extn_compress_voip_is_active(in->dev)) &&
8047 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8048 valid_rate && valid_ch) {
8049 voice_extn_compress_voip_open_input_stream(in);
8050 // update rate entries to match config from AF
8051 in->config.rate = config->sample_rate;
8052 in->sample_rate = config->sample_rate;
8053 } else {
8054 ALOGW("%s compress voip not active, use defaults", __func__);
8055 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008056 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008057 return 0;
8058}
8059
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008060static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008061 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008062 audio_devices_t devices,
8063 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008064 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308065 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008066 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008067 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008068{
8069 struct audio_device *adev = (struct audio_device *)dev;
8070 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008071 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008072 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008073 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308074 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008075 bool is_usb_dev = audio_is_usb_in_device(devices);
8076 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8077 devices,
8078 flags,
8079 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308080
kunleizdff872d2018-08-20 14:40:33 +08008081 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008082 is_usb_dev = false;
8083 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
8084 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
8085 __func__, devices);
8086 }
8087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008088 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008089
8090 if (!(is_usb_dev && may_use_hifi_record)) {
8091 if (config->sample_rate == 0)
8092 config->sample_rate = 48000;
8093 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8094 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8095 if (config->format == AUDIO_FORMAT_DEFAULT)
8096 config->format = AUDIO_FORMAT_PCM_16_BIT;
8097
8098 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
8099
Aalique Grahame22e49102018-12-18 14:23:57 -08008100 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8101 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008102 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05308103 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008104
8105 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008106
8107 if (!in) {
8108 ALOGE("failed to allocate input stream");
8109 return -ENOMEM;
8110 }
8111
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308112 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308113 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
8114 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008115 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008116 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008118 in->stream.common.get_sample_rate = in_get_sample_rate;
8119 in->stream.common.set_sample_rate = in_set_sample_rate;
8120 in->stream.common.get_buffer_size = in_get_buffer_size;
8121 in->stream.common.get_channels = in_get_channels;
8122 in->stream.common.get_format = in_get_format;
8123 in->stream.common.set_format = in_set_format;
8124 in->stream.common.standby = in_standby;
8125 in->stream.common.dump = in_dump;
8126 in->stream.common.set_parameters = in_set_parameters;
8127 in->stream.common.get_parameters = in_get_parameters;
8128 in->stream.common.add_audio_effect = in_add_audio_effect;
8129 in->stream.common.remove_audio_effect = in_remove_audio_effect;
8130 in->stream.set_gain = in_set_gain;
8131 in->stream.read = in_read;
8132 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08008133 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308134 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07008135 in->stream.set_microphone_direction = in_set_microphone_direction;
8136 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07008137 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008138
8139 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008140 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008141 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008142 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008143 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008144 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07008145 in->bit_width = 16;
8146 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07008147 in->direction = MIC_DIRECTION_UNSPECIFIED;
8148 in->zoom = 0;
Haynes Mathew George46740472017-10-27 18:40:12 -07008149
Aalique Grahame22e49102018-12-18 14:23:57 -08008150 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
8151 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
8152 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
8153 /* Force channel config requested to mono if incall
8154 record is being requested for only uplink/downlink */
8155 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
8156 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8157 ret = -EINVAL;
8158 goto err_open;
8159 }
8160 }
8161
Haynes Mathew George46740472017-10-27 18:40:12 -07008162 /* Update config params with the requested sample rate and channels */
8163 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
8164 (adev->mode != AUDIO_MODE_IN_CALL)) {
8165 ret = -EINVAL;
8166 goto err_open;
8167 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008168
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008169 if (is_usb_dev && may_use_hifi_record) {
8170 /* HiFi record selects an appropriate format, channel, rate combo
8171 depending on sink capabilities*/
8172 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
8173 &config->format,
8174 &in->supported_formats[0],
8175 MAX_SUPPORTED_FORMATS,
8176 &config->channel_mask,
8177 &in->supported_channel_masks[0],
8178 MAX_SUPPORTED_CHANNEL_MASKS,
8179 &config->sample_rate,
8180 &in->supported_sample_rates[0],
8181 MAX_SUPPORTED_SAMPLE_RATES);
8182 if (ret != 0) {
8183 ret = -EINVAL;
8184 goto err_open;
8185 }
8186 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008187 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308188 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308189 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8190 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8191 in->config.format = PCM_FORMAT_S32_LE;
8192 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308193 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8194 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8195 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8196 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8197 bool ret_error = false;
8198 in->bit_width = 24;
8199 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8200 from HAL is 24_packed and 8_24
8201 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8202 24_packed return error indicating supported format is 24_packed
8203 *> In case of any other source requesting 24 bit or float return error
8204 indicating format supported is 16 bit only.
8205
8206 on error flinger will retry with supported format passed
8207 */
8208 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8209 (source != AUDIO_SOURCE_CAMCORDER)) {
8210 config->format = AUDIO_FORMAT_PCM_16_BIT;
8211 if (config->sample_rate > 48000)
8212 config->sample_rate = 48000;
8213 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008214 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8215 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308216 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8217 ret_error = true;
8218 }
8219
8220 if (ret_error) {
8221 ret = -EINVAL;
8222 goto err_open;
8223 }
8224 }
8225
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008226 in->channel_mask = config->channel_mask;
8227 in->format = config->format;
8228
8229 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308230
8231 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8232 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8233 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8234 else {
8235 ret = -EINVAL;
8236 goto err_open;
8237 }
8238 }
8239
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008240 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
8241 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8242 is_low_latency = true;
8243#if LOW_LATENCY_CAPTURE_USE_CASE
8244 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8245#endif
8246 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008247 if (!in->realtime) {
8248 in->config = pcm_config_audio_capture;
8249 frame_size = audio_stream_in_frame_size(&in->stream);
8250 buffer_size = get_input_buffer_size(config->sample_rate,
8251 config->format,
8252 channel_count,
8253 is_low_latency);
8254 in->config.period_size = buffer_size / frame_size;
8255 in->config.rate = config->sample_rate;
8256 in->af_period_multiplier = 1;
8257 } else {
8258 // period size is left untouched for rt mode playback
8259 in->config = pcm_config_audio_capture_rt;
8260 in->af_period_multiplier = af_period_multiplier;
8261 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008262 }
8263
8264 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8265 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8266 in->realtime = 0;
8267 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8268 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008269 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008270 in->stream.start = in_start;
8271 in->stream.stop = in_stop;
8272 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8273 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008274 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8275 } else if (in->realtime) {
8276 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008277 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008278 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008279 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008280 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8281 in->config = pcm_config_audio_capture;
8282 frame_size = audio_stream_in_frame_size(&in->stream);
8283 buffer_size = get_input_buffer_size(config->sample_rate,
8284 config->format,
8285 channel_count,
8286 false /*is_low_latency*/);
8287 in->config.period_size = buffer_size / frame_size;
8288 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008289 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008290 switch (config->format) {
8291 case AUDIO_FORMAT_PCM_32_BIT:
8292 in->bit_width = 32;
8293 break;
8294 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8295 case AUDIO_FORMAT_PCM_8_24_BIT:
8296 in->bit_width = 24;
8297 break;
8298 default:
8299 in->bit_width = 16;
8300 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008301 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308302 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008303 if (config->sample_rate == 0)
8304 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8305 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8306 config->sample_rate != 8000) {
8307 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8308 ret = -EINVAL;
8309 goto err_open;
8310 }
8311 if (config->format == AUDIO_FORMAT_DEFAULT)
8312 config->format = AUDIO_FORMAT_PCM_16_BIT;
8313 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8314 config->format = AUDIO_FORMAT_PCM_16_BIT;
8315 ret = -EINVAL;
8316 goto err_open;
8317 }
8318
8319 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8320 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008321 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008322 in->af_period_multiplier = 1;
8323 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8324 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8325 (config->sample_rate == 8000 ||
8326 config->sample_rate == 16000 ||
8327 config->sample_rate == 32000 ||
8328 config->sample_rate == 48000) &&
8329 channel_count == 1) {
8330 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8331 in->config = pcm_config_audio_capture;
8332 frame_size = audio_stream_in_frame_size(&in->stream);
8333 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8334 config->sample_rate,
8335 config->format,
8336 channel_count, false /*is_low_latency*/);
8337 in->config.period_size = buffer_size / frame_size;
8338 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8339 in->config.rate = config->sample_rate;
8340 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008341 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308342 int ret_val;
8343 pthread_mutex_lock(&adev->lock);
8344 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8345 in, config, &channel_mask_updated);
8346 pthread_mutex_unlock(&adev->lock);
8347
8348 if (!ret_val) {
8349 if (channel_mask_updated == true) {
8350 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8351 __func__, config->channel_mask);
8352 ret = -EINVAL;
8353 goto err_open;
8354 }
8355 ALOGD("%s: created multi-channel session succesfully",__func__);
8356 } else if (audio_extn_compr_cap_enabled() &&
8357 audio_extn_compr_cap_format_supported(config->format) &&
8358 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8359 audio_extn_compr_cap_init(in);
8360 } else if (audio_extn_cin_applicable_stream(in)) {
8361 ret = audio_extn_cin_configure_input_stream(in);
8362 if (ret)
8363 goto err_open;
8364 } else {
8365 in->config = pcm_config_audio_capture;
8366 in->config.rate = config->sample_rate;
8367 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308368 in->format = config->format;
8369 frame_size = audio_stream_in_frame_size(&in->stream);
8370 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07008371 config->format,
8372 channel_count,
8373 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02008374 /* prevent division-by-zero */
8375 if (frame_size == 0) {
8376 ALOGE("%s: Error frame_size==0", __func__);
8377 ret = -EINVAL;
8378 goto err_open;
8379 }
8380
Revathi Uddarajud2634032017-12-07 14:42:34 +05308381 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08008382 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008383
Revathi Uddarajud2634032017-12-07 14:42:34 +05308384 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
8385 /* optionally use VOIP usecase depending on config(s) */
8386 ret = adev_update_voice_comm_input_stream(in, config);
8387 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008388
Revathi Uddarajud2634032017-12-07 14:42:34 +05308389 if (ret) {
8390 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
8391 goto err_open;
8392 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008393 }
Samyak Jainc37062f2019-04-25 18:41:06 +05308394 if (audio_extn_is_concurrent_capture_enabled()) {
8395 /* Acquire lock to avoid two concurrent use cases initialized to
8396 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08008397
Samyak Jainc37062f2019-04-25 18:41:06 +05308398 if (in->usecase == USECASE_AUDIO_RECORD) {
8399 pthread_mutex_lock(&adev->lock);
8400 if (!(adev->pcm_record_uc_state)) {
8401 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
8402 adev->pcm_record_uc_state = 1;
8403 pthread_mutex_unlock(&adev->lock);
8404 } else {
8405 pthread_mutex_unlock(&adev->lock);
8406 /* Assign compress record use case for second record */
8407 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
8408 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
8409 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
8410 if (audio_extn_cin_applicable_stream(in)) {
8411 in->sample_rate = config->sample_rate;
8412 ret = audio_extn_cin_configure_input_stream(in);
8413 if (ret)
8414 goto err_open;
8415 }
8416 }
8417 }
kunleiz28c73e72019-03-27 17:24:04 +08008418 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008419 }
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008420
8421 in->config.channels = channel_count;
8422 in->sample_rate = in->config.rate;
8423
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308424 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
8425 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008426 devices, flags, in->format,
8427 in->sample_rate, in->bit_width,
8428 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308429 register_format(in->format, in->supported_formats);
8430 register_channel_mask(in->channel_mask, in->supported_channel_masks);
8431 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308432
Aalique Grahame22e49102018-12-18 14:23:57 -08008433 in->error_log = error_log_create(
8434 ERROR_LOG_ENTRIES,
8435 1000000000 /* aggregate consecutive identical errors within one second */);
8436
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008437 /* This stream could be for sound trigger lab,
8438 get sound trigger pcm if present */
8439 audio_extn_sound_trigger_check_and_get_session(in);
8440
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308441 lock_input_stream(in);
8442 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
8443 pthread_mutex_lock(&adev->lock);
8444 in->card_status = adev->card_status;
8445 pthread_mutex_unlock(&adev->lock);
8446 pthread_mutex_unlock(&in->lock);
8447
Aalique Grahame22e49102018-12-18 14:23:57 -08008448 stream_app_type_cfg_init(&in->app_type_cfg);
8449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008450 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08008451
8452 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
8453 calloc(1, sizeof(streams_input_ctxt_t));
8454 if (in_ctxt == NULL) {
8455 ALOGE("%s fail to allocate input ctxt", __func__);
8456 ret = -ENOMEM;
8457 goto err_open;
8458 }
8459 in_ctxt->input = in;
8460
8461 pthread_mutex_lock(&adev->lock);
8462 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
8463 pthread_mutex_unlock(&adev->lock);
8464
Eric Laurent994a6932013-07-17 11:51:42 -07008465 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008466 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008467
8468err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05308469 if (in->usecase == USECASE_AUDIO_RECORD) {
8470 pthread_mutex_lock(&adev->lock);
8471 adev->pcm_record_uc_state = 0;
8472 pthread_mutex_unlock(&adev->lock);
8473 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008474 free(in);
8475 *stream_in = NULL;
8476 return ret;
8477}
8478
8479static void adev_close_input_stream(struct audio_hw_device *dev,
8480 struct audio_stream_in *stream)
8481{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008482 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008483 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008484 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308485
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308486 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008487
kunleiz70e57612018-12-28 17:50:23 +08008488 /* must deregister from sndmonitor first to prevent races
8489 * between the callback and close_stream
8490 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308491 audio_extn_snd_mon_unregister_listener(stream);
8492
kunleiz70e57612018-12-28 17:50:23 +08008493 /* Disable echo reference if there are no active input, hfp call
8494 * and sound trigger while closing input stream
8495 */
8496 if (!adev->active_input &&
8497 !audio_extn_hfp_is_active(adev) &&
8498 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08008499 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08008500 else
8501 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05308502
Pallavid7c7a272018-01-16 11:22:55 +05308503 if (in == NULL) {
8504 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
8505 return;
8506 }
Weiyin Jiang2995f662019-04-17 14:25:12 +08008507 error_log_destroy(in->error_log);
8508 in->error_log = NULL;
8509
Pallavid7c7a272018-01-16 11:22:55 +05308510
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008511 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308512 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008513 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308514 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008515 if (ret != 0)
8516 ALOGE("%s: Compress voip input cannot be closed, error:%d",
8517 __func__, ret);
8518 } else
8519 in_standby(&stream->common);
8520
Revathi Uddarajud2634032017-12-07 14:42:34 +05308521 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05308522 if (in->usecase == USECASE_AUDIO_RECORD) {
8523 adev->pcm_record_uc_state = 0;
8524 }
8525
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07008526 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008527 audio_extn_ssr_deinit();
8528 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008529
Garmond Leunge2433c32017-09-28 21:51:22 -07008530 if (audio_extn_ffv_get_stream() == in) {
8531 audio_extn_ffv_stream_deinit();
8532 }
8533
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308534 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07008535 audio_extn_compr_cap_format_supported(in->config.format))
8536 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05308537
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308538 if (audio_extn_cin_attached_usecase(in->usecase))
8539 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008540
Mingming Yinfd7607b2016-01-22 12:48:44 -08008541 if (in->is_st_session) {
8542 ALOGV("%s: sound trigger pcm stop lab", __func__);
8543 audio_extn_sound_trigger_stop_lab(in);
8544 }
Derek Chenf939fb72018-11-13 13:34:41 -08008545 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
8546 if (in_ctxt != NULL) {
8547 list_remove(&in_ctxt->list);
8548 free(in_ctxt);
8549 } else {
8550 ALOGW("%s, input stream already closed", __func__);
8551 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008552 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308553 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008554 return;
8555}
8556
Aalique Grahame22e49102018-12-18 14:23:57 -08008557/* verifies input and output devices and their capabilities.
8558 *
8559 * This verification is required when enabling extended bit-depth or
8560 * sampling rates, as not all qcom products support it.
8561 *
8562 * Suitable for calling only on initialization such as adev_open().
8563 * It fills the audio_device use_case_table[] array.
8564 *
8565 * Has a side-effect that it needs to configure audio routing / devices
8566 * in order to power up the devices and read the device parameters.
8567 * It does not acquire any hw device lock. Should restore the devices
8568 * back to "normal state" upon completion.
8569 */
8570static int adev_verify_devices(struct audio_device *adev)
8571{
8572 /* enumeration is a bit difficult because one really wants to pull
8573 * the use_case, device id, etc from the hidden pcm_device_table[].
8574 * In this case there are the following use cases and device ids.
8575 *
8576 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
8577 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
8578 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
8579 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
8580 * [USECASE_AUDIO_RECORD] = {0, 0},
8581 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
8582 * [USECASE_VOICE_CALL] = {2, 2},
8583 *
8584 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
8585 * USECASE_VOICE_CALL omitted, but possible for either input or output.
8586 */
8587
8588 /* should be the usecases enabled in adev_open_input_stream() */
8589 static const int test_in_usecases[] = {
8590 USECASE_AUDIO_RECORD,
8591 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
8592 };
8593 /* should be the usecases enabled in adev_open_output_stream()*/
8594 static const int test_out_usecases[] = {
8595 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
8596 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
8597 };
8598 static const usecase_type_t usecase_type_by_dir[] = {
8599 PCM_PLAYBACK,
8600 PCM_CAPTURE,
8601 };
8602 static const unsigned flags_by_dir[] = {
8603 PCM_OUT,
8604 PCM_IN,
8605 };
8606
8607 size_t i;
8608 unsigned dir;
8609 const unsigned card_id = adev->snd_card;
8610
8611 for (dir = 0; dir < 2; ++dir) {
8612 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
8613 const unsigned flags_dir = flags_by_dir[dir];
8614 const size_t testsize =
8615 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
8616 const int *testcases =
8617 dir ? test_in_usecases : test_out_usecases;
8618 const audio_devices_t audio_device =
8619 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
8620
8621 for (i = 0; i < testsize; ++i) {
8622 const audio_usecase_t audio_usecase = testcases[i];
8623 int device_id;
8624 struct pcm_params **pparams;
8625 struct stream_out out;
8626 struct stream_in in;
8627 struct audio_usecase uc_info;
8628 int retval;
8629
8630 pparams = &adev->use_case_table[audio_usecase];
8631 pcm_params_free(*pparams); /* can accept null input */
8632 *pparams = NULL;
8633
8634 /* find the device ID for the use case (signed, for error) */
8635 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
8636 if (device_id < 0)
8637 continue;
8638
8639 /* prepare structures for device probing */
8640 memset(&uc_info, 0, sizeof(uc_info));
8641 uc_info.id = audio_usecase;
8642 uc_info.type = usecase_type;
8643 if (dir) {
8644 adev->active_input = &in;
8645 memset(&in, 0, sizeof(in));
8646 in.device = audio_device;
8647 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
8648 uc_info.stream.in = &in;
8649 } else {
8650 adev->active_input = NULL;
8651 }
8652 memset(&out, 0, sizeof(out));
8653 out.devices = audio_device; /* only field needed in select_devices */
8654 uc_info.stream.out = &out;
8655 uc_info.devices = audio_device;
8656 uc_info.in_snd_device = SND_DEVICE_NONE;
8657 uc_info.out_snd_device = SND_DEVICE_NONE;
8658 list_add_tail(&adev->usecase_list, &uc_info.list);
8659
8660 /* select device - similar to start_(in/out)put_stream() */
8661 retval = select_devices(adev, audio_usecase);
8662 if (retval >= 0) {
8663 *pparams = pcm_params_get(card_id, device_id, flags_dir);
8664#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07008665 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08008666 if (*pparams) {
8667 ALOGV("%s: (%s) card %d device %d", __func__,
8668 dir ? "input" : "output", card_id, device_id);
8669 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
8670 } else {
8671 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
8672 }
8673#endif
8674 }
8675
8676 /* deselect device - similar to stop_(in/out)put_stream() */
8677 /* 1. Get and set stream specific mixer controls */
8678 retval = disable_audio_route(adev, &uc_info);
8679 /* 2. Disable the rx device */
8680 retval = disable_snd_device(adev,
8681 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
8682 list_remove(&uc_info.list);
8683 }
8684 }
8685 adev->active_input = NULL; /* restore adev state */
8686 return 0;
8687}
8688
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308689int adev_create_audio_patch(struct audio_hw_device *dev,
8690 unsigned int num_sources,
8691 const struct audio_port_config *sources,
8692 unsigned int num_sinks,
8693 const struct audio_port_config *sinks,
8694 audio_patch_handle_t *handle)
8695{
Derek Chenf939fb72018-11-13 13:34:41 -08008696 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308697
Derek Chenf939fb72018-11-13 13:34:41 -08008698 ret = audio_extn_hw_loopback_create_audio_patch(dev,
8699 num_sources,
8700 sources,
8701 num_sinks,
8702 sinks,
8703 handle);
8704 ret |= audio_extn_auto_hal_create_audio_patch(dev,
8705 num_sources,
8706 sources,
8707 num_sinks,
8708 sinks,
8709 handle);
8710 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308711}
8712
8713int adev_release_audio_patch(struct audio_hw_device *dev,
8714 audio_patch_handle_t handle)
8715{
Derek Chenf939fb72018-11-13 13:34:41 -08008716 int ret;
8717
8718 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
8719 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
8720 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308721}
8722
8723int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
8724{
8725 return audio_extn_hw_loopback_get_audio_port(dev, config);
8726}
8727
8728int adev_set_audio_port_config(struct audio_hw_device *dev,
8729 const struct audio_port_config *config)
8730{
8731 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
8732}
8733
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008734static int adev_dump(const audio_hw_device_t *device __unused,
8735 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008736{
8737 return 0;
8738}
8739
8740static int adev_close(hw_device_t *device)
8741{
Aalique Grahame22e49102018-12-18 14:23:57 -08008742 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008743 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07008744
8745 if (!adev)
8746 return 0;
8747
8748 pthread_mutex_lock(&adev_init_lock);
8749
8750 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308751 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008752 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08008753 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008754 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08008755 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308756 audio_extn_utils_release_streams_cfg_lists(
8757 &adev->streams_output_cfg_list,
8758 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308759 if (audio_extn_qaf_is_enabled())
8760 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008761 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08008762 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07008763 free(adev->snd_dev_ref_cnt);
8764 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08008765 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
8766 pcm_params_free(adev->use_case_table[i]);
8767 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008768 if (adev->adm_deinit)
8769 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308770 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008771 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308772 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308773 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008774 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308775 if (adev->device_cfg_params) {
8776 free(adev->device_cfg_params);
8777 adev->device_cfg_params = NULL;
8778 }
Derek Chend2530072014-11-24 12:39:14 -08008779 if(adev->ext_hw_plugin)
8780 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08008781 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008782 free(device);
8783 adev = NULL;
8784 }
8785 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05308786 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008787 return 0;
8788}
8789
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008790/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
8791 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
8792 * just that it _might_ work.
8793 */
8794static int period_size_is_plausible_for_low_latency(int period_size)
8795{
8796 switch (period_size) {
8797 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07008798 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008799 case 240:
8800 case 320:
8801 case 480:
8802 return 1;
8803 default:
8804 return 0;
8805 }
8806}
8807
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308808static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
8809{
8810 bool is_snd_card_status = false;
8811 bool is_ext_device_status = false;
8812 char value[32];
8813 int card = -1;
8814 card_status_t status;
8815
8816 if (cookie != adev || !parms)
8817 return;
8818
8819 if (!parse_snd_card_status(parms, &card, &status)) {
8820 is_snd_card_status = true;
8821 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
8822 is_ext_device_status = true;
8823 } else {
8824 // not a valid event
8825 return;
8826 }
8827
8828 pthread_mutex_lock(&adev->lock);
8829 if (card == adev->snd_card || is_ext_device_status) {
8830 if (is_snd_card_status && adev->card_status != status) {
8831 adev->card_status = status;
8832 platform_snd_card_update(adev->platform, status);
8833 audio_extn_fm_set_parameters(adev, parms);
8834 } else if (is_ext_device_status) {
8835 platform_set_parameters(adev->platform, parms);
8836 }
8837 }
8838 pthread_mutex_unlock(&adev->lock);
8839 return;
8840}
8841
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308842/* out and adev lock held */
8843static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
8844{
8845 struct audio_usecase *uc_info;
8846 float left_p;
8847 float right_p;
8848 audio_devices_t devices;
8849
8850 uc_info = get_usecase_from_list(adev, out->usecase);
8851 if (uc_info == NULL) {
8852 ALOGE("%s: Could not find the usecase (%d) in the list",
8853 __func__, out->usecase);
8854 return -EINVAL;
8855 }
8856
8857 ALOGD("%s: enter: usecase(%d: %s)", __func__,
8858 out->usecase, use_case_table[out->usecase]);
8859
8860 if (restore) {
8861 // restore A2DP device for active usecases and unmute if required
8862 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
8863 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
8864 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
8865 select_devices(adev, uc_info->id);
8866 pthread_mutex_lock(&out->compr_mute_lock);
8867 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8868 (out->a2dp_compress_mute)) {
8869 out->a2dp_compress_mute = false;
8870 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
8871 }
8872 pthread_mutex_unlock(&out->compr_mute_lock);
8873 }
8874 } else {
8875 // mute compress stream if suspended
8876 pthread_mutex_lock(&out->compr_mute_lock);
8877 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8878 (!out->a2dp_compress_mute)) {
8879 if (!out->standby) {
8880 ALOGD("%s: selecting speaker and muting stream", __func__);
8881 devices = out->devices;
8882 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
8883 left_p = out->volume_l;
8884 right_p = out->volume_r;
8885 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8886 compress_pause(out->compr);
8887 out_set_compr_volume(&out->stream, (float)0, (float)0);
8888 out->a2dp_compress_mute = true;
8889 select_devices(adev, out->usecase);
8890 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8891 compress_resume(out->compr);
8892 out->devices = devices;
8893 out->volume_l = left_p;
8894 out->volume_r = right_p;
8895 }
8896 }
8897 pthread_mutex_unlock(&out->compr_mute_lock);
8898 }
8899 ALOGV("%s: exit", __func__);
8900 return 0;
8901}
8902
8903int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
8904{
8905 int ret = 0;
8906
8907 lock_output_stream(out);
8908 pthread_mutex_lock(&adev->lock);
8909
8910 ret = check_a2dp_restore_l(adev, out, restore);
8911
8912 pthread_mutex_unlock(&adev->lock);
8913 pthread_mutex_unlock(&out->lock);
8914 return ret;
8915}
8916
Haynes Mathew George01156f92018-04-13 15:29:54 -07008917void adev_on_battery_status_changed(bool charging)
8918{
8919 pthread_mutex_lock(&adev->lock);
8920 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
8921 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08008922 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07008923 pthread_mutex_unlock(&adev->lock);
8924}
8925
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008926static int adev_open(const hw_module_t *module, const char *name,
8927 hw_device_t **device)
8928{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308929 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08008930 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308931 char mixer_ctl_name[128] = {0};
8932 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308933
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008934 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008935 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
8936
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008937 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07008938 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008939 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07008940 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008941 ALOGD("%s: returning existing instance of adev", __func__);
8942 ALOGD("%s: exit", __func__);
8943 pthread_mutex_unlock(&adev_init_lock);
8944 return 0;
8945 }
8946
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008947 adev = calloc(1, sizeof(struct audio_device));
8948
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008949 if (!adev) {
8950 pthread_mutex_unlock(&adev_init_lock);
8951 return -ENOMEM;
8952 }
8953
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008954 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
8955
Weiyin Jiange6ce6312019-01-28 18:28:22 +08008956 // register audio ext hidl at the earliest
8957 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05308958#ifdef DYNAMIC_LOG_ENABLED
8959 register_for_dynamic_logging("hal");
8960#endif
8961
Derek Chenf939fb72018-11-13 13:34:41 -08008962 /* default audio HAL major version */
8963 uint32_t maj_version = 2;
8964 if(property_get("vendor.audio.hal.maj.version", value, NULL))
8965 maj_version = atoi(value);
8966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008967 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08008968 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008969 adev->device.common.module = (struct hw_module_t *)module;
8970 adev->device.common.close = adev_close;
8971
8972 adev->device.init_check = adev_init_check;
8973 adev->device.set_voice_volume = adev_set_voice_volume;
8974 adev->device.set_master_volume = adev_set_master_volume;
8975 adev->device.get_master_volume = adev_get_master_volume;
8976 adev->device.set_master_mute = adev_set_master_mute;
8977 adev->device.get_master_mute = adev_get_master_mute;
8978 adev->device.set_mode = adev_set_mode;
8979 adev->device.set_mic_mute = adev_set_mic_mute;
8980 adev->device.get_mic_mute = adev_get_mic_mute;
8981 adev->device.set_parameters = adev_set_parameters;
8982 adev->device.get_parameters = adev_get_parameters;
8983 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
8984 adev->device.open_output_stream = adev_open_output_stream;
8985 adev->device.close_output_stream = adev_close_output_stream;
8986 adev->device.open_input_stream = adev_open_input_stream;
8987 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308988 adev->device.create_audio_patch = adev_create_audio_patch;
8989 adev->device.release_audio_patch = adev_release_audio_patch;
8990 adev->device.get_audio_port = adev_get_audio_port;
8991 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008992 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308993 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008994
8995 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008996 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08008997 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008998 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008999 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009000 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08009001 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07009002 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309003 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07009004 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07009005 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Aniket Kumar Lata808e8d62019-01-28 22:54:28 -08009006 /* Init audio feature manager */
9007 audio_feature_manager_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009008 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08009009 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08009010 list_init(&adev->active_inputs_list);
9011 list_init(&adev->active_outputs_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08009012 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009013 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05309014 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05309015 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309016 adev->perf_lock_opts[0] = 0x101;
9017 adev->perf_lock_opts[1] = 0x20E;
9018 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009019 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07009020 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309021 adev->use_old_pspd_mix_ctrl = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309022
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009023 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07009024 adev->platform = platform_init(adev);
9025 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009026 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009027 free(adev->snd_dev_ref_cnt);
9028 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009029 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07009030 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9031 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08009032 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009033 return -EINVAL;
9034 }
Eric Laurentc4aef752013-09-12 17:45:53 -07009035
Aalique Grahame22e49102018-12-18 14:23:57 -08009036 adev->extspk = audio_extn_extspk_init(adev);
9037
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309038 if (audio_extn_qaf_is_enabled()) {
9039 ret = audio_extn_qaf_init(adev);
9040 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009041 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309042 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009043 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309044 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9045 *device = NULL;
9046 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309047 return ret;
9048 }
9049
9050 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
9051 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
9052 }
9053
Derek Chenae7b0342019-02-08 15:17:04 -08009054 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08009055 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
9056
Eric Laurentc4aef752013-09-12 17:45:53 -07009057 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
9058 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
9059 if (adev->visualizer_lib == NULL) {
9060 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
9061 } else {
9062 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
9063 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009064 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009065 "visualizer_hal_start_output");
9066 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009067 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009068 "visualizer_hal_stop_output");
9069 }
9070 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05309071 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009072 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08009073 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08009074 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309075 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009076 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07009077
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009078 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
9079 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
9080 if (adev->offload_effects_lib == NULL) {
9081 ALOGE("%s: DLOPEN failed for %s", __func__,
9082 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9083 } else {
9084 ALOGV("%s: DLOPEN successful for %s", __func__,
9085 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9086 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05309087 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009088 "offload_effects_bundle_hal_start_output");
9089 adev->offload_effects_stop_output =
9090 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
9091 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009092 adev->offload_effects_set_hpx_state =
9093 (int (*)(bool))dlsym(adev->offload_effects_lib,
9094 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05309095 adev->offload_effects_get_parameters =
9096 (void (*)(struct str_parms *, struct str_parms *))
9097 dlsym(adev->offload_effects_lib,
9098 "offload_effects_bundle_get_parameters");
9099 adev->offload_effects_set_parameters =
9100 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
9101 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009102 }
9103 }
9104
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009105 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
9106 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
9107 if (adev->adm_lib == NULL) {
9108 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
9109 } else {
9110 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
9111 adev->adm_init = (adm_init_t)
9112 dlsym(adev->adm_lib, "adm_init");
9113 adev->adm_deinit = (adm_deinit_t)
9114 dlsym(adev->adm_lib, "adm_deinit");
9115 adev->adm_register_input_stream = (adm_register_input_stream_t)
9116 dlsym(adev->adm_lib, "adm_register_input_stream");
9117 adev->adm_register_output_stream = (adm_register_output_stream_t)
9118 dlsym(adev->adm_lib, "adm_register_output_stream");
9119 adev->adm_deregister_stream = (adm_deregister_stream_t)
9120 dlsym(adev->adm_lib, "adm_deregister_stream");
9121 adev->adm_request_focus = (adm_request_focus_t)
9122 dlsym(adev->adm_lib, "adm_request_focus");
9123 adev->adm_abandon_focus = (adm_abandon_focus_t)
9124 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009125 adev->adm_set_config = (adm_set_config_t)
9126 dlsym(adev->adm_lib, "adm_set_config");
9127 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
9128 dlsym(adev->adm_lib, "adm_request_focus_v2");
9129 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
9130 dlsym(adev->adm_lib, "adm_is_noirq_avail");
9131 adev->adm_on_routing_change = (adm_on_routing_change_t)
9132 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009133 }
9134 }
9135
Aalique Grahame22e49102018-12-18 14:23:57 -08009136 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009137 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +08009138 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009139 //initialize this to false for now,
9140 //this will be set to true through set param
9141 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009142
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07009143 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009144 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08009145
9146 if (k_enable_extended_precision)
9147 adev_verify_devices(adev);
9148
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009149 adev->dsp_bit_width_enforce_mode =
9150 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009151
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309152 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
9153 &adev->streams_output_cfg_list,
9154 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07009155
Kiran Kandi910e1862013-10-29 13:29:42 -07009156 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009157
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009158 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08009159 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
9160 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009161 trial = atoi(value);
9162 if (period_size_is_plausible_for_low_latency(trial)) {
9163 pcm_config_low_latency.period_size = trial;
9164 pcm_config_low_latency.start_threshold = trial / 4;
9165 pcm_config_low_latency.avail_min = trial / 4;
9166 configured_low_latency_capture_period_size = trial;
9167 }
9168 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009169 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
9170 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009171 trial = atoi(value);
9172 if (period_size_is_plausible_for_low_latency(trial)) {
9173 configured_low_latency_capture_period_size = trial;
9174 }
9175 }
9176
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08009177 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
9178
Aalique Grahame22e49102018-12-18 14:23:57 -08009179 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
9180 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009181 af_period_multiplier = atoi(value);
9182 if (af_period_multiplier < 0)
9183 af_period_multiplier = 2;
9184 else if (af_period_multiplier > 4)
9185 af_period_multiplier = 4;
9186
9187 ALOGV("new period_multiplier = %d", af_period_multiplier);
9188 }
9189
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009190 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009191
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009192 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009193 pthread_mutex_unlock(&adev_init_lock);
9194
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009195 if (adev->adm_init)
9196 adev->adm_data = adev->adm_init();
9197
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309198 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309199 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009200 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309201
9202 audio_extn_snd_mon_init();
9203 pthread_mutex_lock(&adev->lock);
9204 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9205 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009206 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9207 /*
9208 * if the battery state callback happens before charging can be queried,
9209 * it will be guarded with the adev->lock held in the cb function and so
9210 * the callback value will reflect the latest state
9211 */
9212 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309213 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009214 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -07009215 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +08009216 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309217 /* Allocate memory for Device config params */
9218 adev->device_cfg_params = (struct audio_device_config_param*)
9219 calloc(platform_get_max_codec_backend(),
9220 sizeof(struct audio_device_config_param));
9221 if (adev->device_cfg_params == NULL)
9222 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309223
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309224 /*
9225 * Check if new PSPD matrix mixer control is supported. If not
9226 * supported, then set flag so that old mixer ctrl is sent while
9227 * sending pspd coefficients on older kernel version. Query mixer
9228 * control for default pcm id and channel value one.
9229 */
9230 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
9231 "AudStr %d ChMixer Weight Ch %d", 0, 1);
9232
9233 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
9234 if (!ctl) {
9235 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
9236 __func__, mixer_ctl_name);
9237 adev->use_old_pspd_mix_ctrl = true;
9238 }
9239
Eric Laurent994a6932013-07-17 11:51:42 -07009240 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009241 return 0;
9242}
9243
9244static struct hw_module_methods_t hal_module_methods = {
9245 .open = adev_open,
9246};
9247
9248struct audio_module HAL_MODULE_INFO_SYM = {
9249 .common = {
9250 .tag = HARDWARE_MODULE_TAG,
9251 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9252 .hal_api_version = HARDWARE_HAL_API_VERSION,
9253 .id = AUDIO_HARDWARE_MODULE_ID,
9254 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009255 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009256 .methods = &hal_module_methods,
9257 },
9258};