blob: 8b44cd591e76531a6829dedd311e6a4ac739cbe7 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05302 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
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"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080076
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070077#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080078#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080079
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053080#ifdef DYNAMIC_LOG_ENABLED
81#include <log_xml_parser.h>
82#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
83#include <log_utils.h>
84#endif
85
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053087/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
88#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070089#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070090#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053091#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070092
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070093#define PROXY_OPEN_RETRY_COUNT 100
94#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080095
Mingming Yin08c7e312015-03-16 18:10:58 -070096#ifdef USE_LL_AS_PRIMARY_OUTPUT
97#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
98#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
99#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800100#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700101#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
102#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800103
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700104#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700105#define DEFAULT_VOIP_BUF_DURATION_MS 20
106#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
107#define DEFAULT_VOIP_SAMP_RATE 48000
108
109#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
110
111struct pcm_config default_pcm_config_voip_copp = {
112 .channels = 1,
113 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
114 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
115 .period_count = 2,
116 .format = PCM_FORMAT_S16_LE,
117};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700118
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700119static unsigned int configured_low_latency_capture_period_size =
120 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
121
Haynes Mathew George16081042017-05-31 17:16:49 -0700122#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
123#define MMAP_PERIOD_COUNT_MIN 32
124#define MMAP_PERIOD_COUNT_MAX 512
125#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
126
Eric Laurentb23d5282013-05-14 15:27:20 -0700127struct pcm_config pcm_config_deep_buffer = {
128 .channels = 2,
129 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
130 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
131 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
132 .format = PCM_FORMAT_S16_LE,
133 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
134 .stop_threshold = INT_MAX,
135 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
136};
137
138struct pcm_config pcm_config_low_latency = {
139 .channels = 2,
140 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
141 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
142 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
143 .format = PCM_FORMAT_S16_LE,
144 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
145 .stop_threshold = INT_MAX,
146 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
147};
148
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700149static int af_period_multiplier = 4;
150struct pcm_config pcm_config_rt = {
151 .channels = 2,
152 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
153 .period_size = ULL_PERIOD_SIZE, //1 ms
154 .period_count = 512, //=> buffer size is 512ms
155 .format = PCM_FORMAT_S16_LE,
156 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
157 .stop_threshold = INT_MAX,
158 .silence_threshold = 0,
159 .silence_size = 0,
160 .avail_min = ULL_PERIOD_SIZE, //1 ms
161};
162
Eric Laurentb23d5282013-05-14 15:27:20 -0700163struct pcm_config pcm_config_hdmi_multi = {
164 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
165 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
166 .period_size = HDMI_MULTI_PERIOD_SIZE,
167 .period_count = HDMI_MULTI_PERIOD_COUNT,
168 .format = PCM_FORMAT_S16_LE,
169 .start_threshold = 0,
170 .stop_threshold = INT_MAX,
171 .avail_min = 0,
172};
173
Haynes Mathew George16081042017-05-31 17:16:49 -0700174struct pcm_config pcm_config_mmap_playback = {
175 .channels = 2,
176 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
177 .period_size = MMAP_PERIOD_SIZE,
178 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
179 .format = PCM_FORMAT_S16_LE,
180 .start_threshold = MMAP_PERIOD_SIZE*8,
181 .stop_threshold = INT32_MAX,
182 .silence_threshold = 0,
183 .silence_size = 0,
184 .avail_min = MMAP_PERIOD_SIZE, //1 ms
185};
186
Eric Laurentb23d5282013-05-14 15:27:20 -0700187struct pcm_config pcm_config_audio_capture = {
188 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700189 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
190 .format = PCM_FORMAT_S16_LE,
191};
192
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700193struct pcm_config pcm_config_audio_capture_rt = {
194 .channels = 2,
195 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
196 .period_size = ULL_PERIOD_SIZE,
197 .period_count = 512,
198 .format = PCM_FORMAT_S16_LE,
199 .start_threshold = 0,
200 .stop_threshold = INT_MAX,
201 .silence_threshold = 0,
202 .silence_size = 0,
203 .avail_min = ULL_PERIOD_SIZE, //1 ms
204};
205
Haynes Mathew George16081042017-05-31 17:16:49 -0700206struct pcm_config pcm_config_mmap_capture = {
207 .channels = 2,
208 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
209 .period_size = MMAP_PERIOD_SIZE,
210 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
211 .format = PCM_FORMAT_S16_LE,
212 .start_threshold = 0,
213 .stop_threshold = INT_MAX,
214 .silence_threshold = 0,
215 .silence_size = 0,
216 .avail_min = MMAP_PERIOD_SIZE, //1 ms
217};
218
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700219#define AFE_PROXY_CHANNEL_COUNT 2
220#define AFE_PROXY_SAMPLING_RATE 48000
221
222#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
223#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
224
225struct pcm_config pcm_config_afe_proxy_playback = {
226 .channels = AFE_PROXY_CHANNEL_COUNT,
227 .rate = AFE_PROXY_SAMPLING_RATE,
228 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
229 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
230 .format = PCM_FORMAT_S16_LE,
231 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
232 .stop_threshold = INT_MAX,
233 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
234};
235
236#define AFE_PROXY_RECORD_PERIOD_SIZE 768
237#define AFE_PROXY_RECORD_PERIOD_COUNT 4
238
239struct pcm_config pcm_config_afe_proxy_record = {
240 .channels = AFE_PROXY_CHANNEL_COUNT,
241 .rate = AFE_PROXY_SAMPLING_RATE,
242 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
243 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
244 .format = PCM_FORMAT_S16_LE,
245 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
246 .stop_threshold = INT_MAX,
247 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
248};
249
Ashish Jainf1eaa582016-05-23 20:54:24 +0530250#define AUDIO_MAX_PCM_FORMATS 7
251
252const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
253 [AUDIO_FORMAT_DEFAULT] = 0,
254 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
255 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
256 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
257 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
258 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
259 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
260};
261
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800262const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700263 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
264 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700265 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
266 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700267 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700268 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700269 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
270 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
271 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
272 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
273 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
274 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
275 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
276 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700277 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
278 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700279
Eric Laurentb23d5282013-05-14 15:27:20 -0700280 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700281 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530282 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
283 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
284 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700285 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700286 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700287 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
288
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800289 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800290 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700291 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700292
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700293 [USECASE_VOICE2_CALL] = "voice2-call",
294 [USECASE_VOLTE_CALL] = "volte-call",
295 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800296 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800297 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
298 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800299 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700300 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
301 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
302 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800303 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
304 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
305 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
306
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700307 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
308 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700309 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
310 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700311
312 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
313 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700314 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700315
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530316 /* Transcode loopback cases */
317 [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700318
319 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
320 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Eric Laurentb23d5282013-05-14 15:27:20 -0700321};
322
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700323static const audio_usecase_t offload_usecases[] = {
324 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700325 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
326 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
327 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
328 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
329 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
330 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
331 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
332 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700333};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800334
335#define STRING_TO_ENUM(string) { #string, string }
336
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800337struct string_to_enum {
338 const char *name;
339 uint32_t value;
340};
341
342static const struct string_to_enum out_channels_name_to_enum_table[] = {
343 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800344 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
345 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
346 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700347 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800348 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
349 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800350 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
351};
352
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700353static const struct string_to_enum out_formats_name_to_enum_table[] = {
354 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
355 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
356 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700357 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800358 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
359 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700360 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800361};
362
363//list of all supported sample rates by HDMI specification.
364static const int out_hdmi_sample_rates[] = {
365 32000, 44100, 48000, 88200, 96000, 176400, 192000,
366};
367
368static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
369 STRING_TO_ENUM(32000),
370 STRING_TO_ENUM(44100),
371 STRING_TO_ENUM(48000),
372 STRING_TO_ENUM(88200),
373 STRING_TO_ENUM(96000),
374 STRING_TO_ENUM(176400),
375 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700376};
377
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700378static struct audio_device *adev = NULL;
379static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700380static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700381//cache last MBDRC cal step level
382static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700383
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530384static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
385static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
386
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700387static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
388 int flags __unused)
389{
390 int dir = 0;
391 switch (uc_id) {
392 case USECASE_AUDIO_RECORD_LOW_LATENCY:
393 dir = 1;
394 case USECASE_AUDIO_PLAYBACK_ULL:
395 break;
396 default:
397 return false;
398 }
399
400 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
401 PCM_PLAYBACK : PCM_CAPTURE);
402 if (adev->adm_is_noirq_avail)
403 return adev->adm_is_noirq_avail(adev->adm_data,
404 adev->snd_card, dev_id, dir);
405 return false;
406}
407
408static void register_out_stream(struct stream_out *out)
409{
410 struct audio_device *adev = out->dev;
411 if (is_offload_usecase(out->usecase) ||
412 !adev->adm_register_output_stream)
413 return;
414
415 // register stream first for backward compatibility
416 adev->adm_register_output_stream(adev->adm_data,
417 out->handle,
418 out->flags);
419
420 if (!adev->adm_set_config)
421 return;
422
423 if (out->realtime)
424 adev->adm_set_config(adev->adm_data,
425 out->handle,
426 out->pcm, &out->config);
427}
428
429static void register_in_stream(struct stream_in *in)
430{
431 struct audio_device *adev = in->dev;
432 if (!adev->adm_register_input_stream)
433 return;
434
435 adev->adm_register_input_stream(adev->adm_data,
436 in->capture_handle,
437 in->flags);
438
439 if (!adev->adm_set_config)
440 return;
441
442 if (in->realtime)
443 adev->adm_set_config(adev->adm_data,
444 in->capture_handle,
445 in->pcm,
446 &in->config);
447}
448
449static void request_out_focus(struct stream_out *out, long ns)
450{
451 struct audio_device *adev = out->dev;
452
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700453 if (adev->adm_request_focus_v2)
454 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
455 else if (adev->adm_request_focus)
456 adev->adm_request_focus(adev->adm_data, out->handle);
457}
458
459static void request_in_focus(struct stream_in *in, long ns)
460{
461 struct audio_device *adev = in->dev;
462
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700463 if (adev->adm_request_focus_v2)
464 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
465 else if (adev->adm_request_focus)
466 adev->adm_request_focus(adev->adm_data, in->capture_handle);
467}
468
469static void release_out_focus(struct stream_out *out)
470{
471 struct audio_device *adev = out->dev;
472
473 if (adev->adm_abandon_focus)
474 adev->adm_abandon_focus(adev->adm_data, out->handle);
475}
476
477static void release_in_focus(struct stream_in *in)
478{
479 struct audio_device *adev = in->dev;
480 if (adev->adm_abandon_focus)
481 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
482}
483
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530484static int parse_snd_card_status(struct str_parms *parms, int *card,
485 card_status_t *status)
486{
487 char value[32]={0};
488 char state[32]={0};
489
490 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
491 if (ret < 0)
492 return -1;
493
494 // sscanf should be okay as value is of max length 32.
495 // same as sizeof state.
496 if (sscanf(value, "%d,%s", card, state) < 2)
497 return -1;
498
499 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
500 CARD_STATUS_OFFLINE;
501 return 0;
502}
503
vivek mehtaa76401a2015-04-24 14:12:15 -0700504__attribute__ ((visibility ("default")))
505bool audio_hw_send_gain_dep_calibration(int level) {
506 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700507 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700508
509 pthread_mutex_lock(&adev_init_lock);
510
511 if (adev != NULL && adev->platform != NULL) {
512 pthread_mutex_lock(&adev->lock);
513 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700514
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530515 // cache level info for any of the use case which
516 // was not started.
517 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700518
vivek mehtaa76401a2015-04-24 14:12:15 -0700519 pthread_mutex_unlock(&adev->lock);
520 } else {
521 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
522 }
523
524 pthread_mutex_unlock(&adev_init_lock);
525
526 return ret_val;
527}
528
Ashish Jain5106d362016-05-11 19:23:33 +0530529static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
530{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800531 bool gapless_enabled = false;
532 const char *mixer_ctl_name = "Compress Gapless Playback";
533 struct mixer_ctl *ctl;
534
535 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700536 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530537
538 /*Disable gapless if its AV playback*/
539 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800540
541 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
542 if (!ctl) {
543 ALOGE("%s: Could not get ctl for mixer cmd - %s",
544 __func__, mixer_ctl_name);
545 return -EINVAL;
546 }
547
548 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
549 ALOGE("%s: Could not set gapless mode %d",
550 __func__, gapless_enabled);
551 return -EINVAL;
552 }
553 return 0;
554}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700555
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700556__attribute__ ((visibility ("default")))
557int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
558 int table_size) {
559 int ret_val = 0;
560 ALOGV("%s: enter ... ", __func__);
561
562 pthread_mutex_lock(&adev_init_lock);
563 if (adev == NULL) {
564 ALOGW("%s: adev is NULL .... ", __func__);
565 goto done;
566 }
567
568 pthread_mutex_lock(&adev->lock);
569 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
570 pthread_mutex_unlock(&adev->lock);
571done:
572 pthread_mutex_unlock(&adev_init_lock);
573 ALOGV("%s: exit ... ", __func__);
574 return ret_val;
575}
576
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700577static bool is_supported_format(audio_format_t format)
578{
Eric Laurent86e17132013-09-12 17:49:30 -0700579 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530580 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530581 format == AUDIO_FORMAT_AAC_LC ||
582 format == AUDIO_FORMAT_AAC_HE_V1 ||
583 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530584 format == AUDIO_FORMAT_AAC_ADTS_LC ||
585 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
586 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530587 format == AUDIO_FORMAT_AAC_LATM_LC ||
588 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
589 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530590 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
591 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530592 format == AUDIO_FORMAT_PCM_FLOAT ||
593 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700594 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530595 format == AUDIO_FORMAT_AC3 ||
596 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700597 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530598 format == AUDIO_FORMAT_DTS ||
599 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800600 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530601 format == AUDIO_FORMAT_ALAC ||
602 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530603 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530604 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800605 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530606 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700607 format == AUDIO_FORMAT_APTX ||
608 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800609 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700610
611 return false;
612}
613
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700614static inline bool is_mmap_usecase(audio_usecase_t uc_id)
615{
616 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
617 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
618}
619
Avinash Vaish71a8b972014-07-24 15:36:33 +0530620static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
621 struct audio_usecase *uc_info)
622{
623 struct listnode *node;
624 struct audio_usecase *usecase;
625
626 if (uc_info == NULL)
627 return -EINVAL;
628
629 /* Re-route all voice usecases on the shared backend other than the
630 specified usecase to new snd devices */
631 list_for_each(node, &adev->usecase_list) {
632 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800633 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530634 enable_audio_route(adev, usecase);
635 }
636 return 0;
637}
638
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530639static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530640{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530641 ALOGV("%s", __func__);
642 audio_route_apply_and_update_path(adev->audio_route,
643 "asrc-mode");
644 adev->asrc_mode_enabled = true;
645}
646
647static void disable_asrc_mode(struct audio_device *adev)
648{
649 ALOGV("%s", __func__);
650 audio_route_reset_and_update_path(adev->audio_route,
651 "asrc-mode");
652 adev->asrc_mode_enabled = false;
653}
654
655/*
656 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
657 * 44.1 or Native DSD backends are enabled for any of current use case.
658 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
659 * - Disable current mix path use case(Headphone backend) and re-enable it with
660 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
661 * e.g. Naitve DSD or Headphone 44.1 -> + 48
662 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530663static void check_and_set_asrc_mode(struct audio_device *adev,
664 struct audio_usecase *uc_info,
665 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530666{
667 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530668 int i, num_new_devices = 0;
669 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
670 /*
671 *Split snd device for new combo use case
672 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
673 */
674 if (platform_split_snd_device(adev->platform,
675 snd_device,
676 &num_new_devices,
677 split_new_snd_devices) == 0) {
678 for (i = 0; i < num_new_devices; i++)
679 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
680 } else {
681 int new_backend_idx = platform_get_backend_index(snd_device);
682 if (((new_backend_idx == HEADPHONE_BACKEND) ||
683 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
684 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
685 !adev->asrc_mode_enabled) {
686 struct listnode *node = NULL;
687 struct audio_usecase *uc = NULL;
688 struct stream_out *curr_out = NULL;
689 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
690 int i, num_devices, ret = 0;
691 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530692
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530693 list_for_each(node, &adev->usecase_list) {
694 uc = node_to_item(node, struct audio_usecase, list);
695 curr_out = (struct stream_out*) uc->stream.out;
696 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
697 /*
698 *Split snd device for existing combo use case
699 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
700 */
701 ret = platform_split_snd_device(adev->platform,
702 uc->out_snd_device,
703 &num_devices,
704 split_snd_devices);
705 if (ret < 0 || num_devices == 0) {
706 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
707 split_snd_devices[0] = uc->out_snd_device;
708 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800709 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530710 for (i = 0; i < num_devices; i++) {
711 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
712 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
713 if((new_backend_idx == HEADPHONE_BACKEND) &&
714 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
715 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
716 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
717 __func__);
718 enable_asrc_mode(adev);
719 break;
720 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
721 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
722 (usecase_backend_idx == HEADPHONE_BACKEND)) {
723 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
724 __func__);
725 disable_audio_route(adev, uc);
726 disable_snd_device(adev, uc->out_snd_device);
727 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
728 if (new_backend_idx == DSD_NATIVE_BACKEND)
729 audio_route_apply_and_update_path(adev->audio_route,
730 "hph-true-highquality-mode");
731 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
732 (curr_out->bit_width >= 24))
733 audio_route_apply_and_update_path(adev->audio_route,
734 "hph-highquality-mode");
735 enable_asrc_mode(adev);
736 enable_snd_device(adev, uc->out_snd_device);
737 enable_audio_route(adev, uc);
738 break;
739 }
740 }
741 // reset split devices count
742 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800743 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530744 if (adev->asrc_mode_enabled)
745 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530746 }
747 }
748 }
749}
750
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700751int pcm_ioctl(struct pcm *pcm, int request, ...)
752{
753 va_list ap;
754 void * arg;
755 int pcm_fd = *(int*)pcm;
756
757 va_start(ap, request);
758 arg = va_arg(ap, void *);
759 va_end(ap);
760
761 return ioctl(pcm_fd, request, arg);
762}
763
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700764int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700765 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800766{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700767 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700768 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530769 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800770
771 if (usecase == NULL)
772 return -EINVAL;
773
774 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
775
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800776 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700777 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800778 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700779 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800780
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800781#ifdef DS1_DOLBY_DAP_ENABLED
782 audio_extn_dolby_set_dmid(adev);
783 audio_extn_dolby_set_endpoint(adev);
784#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700785 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700786 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530787 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700788 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530789 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530790 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
791 out = usecase->stream.out;
792 if (out && out->compr)
793 audio_extn_utils_compress_set_clk_rec_mode(usecase);
794 }
795
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800796 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700797 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700798 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700799 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800800 ALOGV("%s: exit", __func__);
801 return 0;
802}
803
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700804int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700805 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800806{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700807 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700808 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800809
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530810 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800811 return -EINVAL;
812
813 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700814 if (usecase->type == PCM_CAPTURE)
815 snd_device = usecase->in_snd_device;
816 else
817 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800818 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700819 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700820 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700821 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700822 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530823 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800824 ALOGV("%s: exit", __func__);
825 return 0;
826}
827
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700828int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700829 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800830{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530831 int i, num_devices = 0;
832 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700833 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
834
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800835 if (snd_device < SND_DEVICE_MIN ||
836 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800837 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800838 return -EINVAL;
839 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700840
841 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700842
843 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
844 ALOGE("%s: Invalid sound device returned", __func__);
845 return -EINVAL;
846 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700847 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700848 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700849 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700850 return 0;
851 }
852
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530853
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700854 if (audio_extn_spkr_prot_is_enabled())
855 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700856
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800857 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
858 audio_extn_spkr_prot_is_enabled()) {
859 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700860 adev->snd_dev_ref_cnt[snd_device]--;
861 return -EINVAL;
862 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200863 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800864 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800865 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200866 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800867 return -EINVAL;
868 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700869 } else if (platform_split_snd_device(adev->platform,
870 snd_device,
871 &num_devices,
872 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530873 for (i = 0; i < num_devices; i++) {
874 enable_snd_device(adev, new_snd_devices[i]);
875 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800876 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700877 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530878
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530879
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530880 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
881 (audio_extn_a2dp_start_playback() < 0)) {
882 ALOGE(" fail to configure A2dp control path ");
883 return -EINVAL;
884 }
885
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700886 /* due to the possibility of calibration overwrite between listen
887 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700888 audio_extn_sound_trigger_update_device_status(snd_device,
889 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530890 audio_extn_listen_update_device_status(snd_device,
891 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700892 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700893 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700894 audio_extn_sound_trigger_update_device_status(snd_device,
895 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530896 audio_extn_listen_update_device_status(snd_device,
897 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700898 return -EINVAL;
899 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300900 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700901 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530902
903 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
904 !adev->native_playback_enabled &&
905 audio_is_true_native_stream_active(adev)) {
906 ALOGD("%s: %d: napb: enabling native mode in hardware",
907 __func__, __LINE__);
908 audio_route_apply_and_update_path(adev->audio_route,
909 "true-native-mode");
910 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530911 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800912 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800913 return 0;
914}
915
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700916int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700917 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800918{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530919 int i, num_devices = 0;
920 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700921 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
922
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800923 if (snd_device < SND_DEVICE_MIN ||
924 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800925 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800926 return -EINVAL;
927 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700928 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
929 ALOGE("%s: device ref cnt is already 0", __func__);
930 return -EINVAL;
931 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700932
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700933 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700934
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700935 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
936 ALOGE("%s: Invalid sound device returned", __func__);
937 return -EINVAL;
938 }
939
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700940 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700941 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530942
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800943 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
944 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700945 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700946 } else if (platform_split_snd_device(adev->platform,
947 snd_device,
948 &num_devices,
949 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530950 for (i = 0; i < num_devices; i++) {
951 disable_snd_device(adev, new_snd_devices[i]);
952 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300953 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700954 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300955 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700956
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530957 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
958 audio_extn_a2dp_stop_playback();
959
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700960 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530961 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530962 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
963 adev->native_playback_enabled) {
964 ALOGD("%s: %d: napb: disabling native mode in hardware",
965 __func__, __LINE__);
966 audio_route_reset_and_update_path(adev->audio_route,
967 "true-native-mode");
968 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530969 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
970 adev->asrc_mode_enabled) {
971 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530972 disable_asrc_mode(adev);
973 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530974 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530975
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200976 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700977 audio_extn_sound_trigger_update_device_status(snd_device,
978 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530979 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800980 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700981 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800983 return 0;
984}
985
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700986/*
987 legend:
988 uc - existing usecase
989 new_uc - new usecase
990 d1, d11, d2 - SND_DEVICE enums
991 a1, a2 - corresponding ANDROID device enums
992 B1, B2 - backend strings
993
994case 1
995 uc->dev d1 (a1) B1
996 new_uc->dev d1 (a1), d2 (a2) B1, B2
997
998 resolution: disable and enable uc->dev on d1
999
1000case 2
1001 uc->dev d1 (a1) B1
1002 new_uc->dev d11 (a1) B1
1003
1004 resolution: need to switch uc since d1 and d11 are related
1005 (e.g. speaker and voice-speaker)
1006 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1007
1008case 3
1009 uc->dev d1 (a1) B1
1010 new_uc->dev d2 (a2) B2
1011
1012 resolution: no need to switch uc
1013
1014case 4
1015 uc->dev d1 (a1) B1
1016 new_uc->dev d2 (a2) B1
1017
1018 resolution: disable enable uc-dev on d2 since backends match
1019 we cannot enable two streams on two different devices if they
1020 share the same backend. e.g. if offload is on speaker device using
1021 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1022 using the same backend, offload must also be switched to voice-handset.
1023
1024case 5
1025 uc->dev d1 (a1) B1
1026 new_uc->dev d1 (a1), d2 (a2) B1
1027
1028 resolution: disable enable uc-dev on d2 since backends match
1029 we cannot enable two streams on two different devices if they
1030 share the same backend.
1031
1032case 6
1033 uc->dev d1 (a1) B1
1034 new_uc->dev d2 (a1) B2
1035
1036 resolution: no need to switch
1037
1038case 7
1039 uc->dev d1 (a1), d2 (a2) B1, B2
1040 new_uc->dev d1 (a1) B1
1041
1042 resolution: no need to switch
1043
1044*/
1045static snd_device_t derive_playback_snd_device(void * platform,
1046 struct audio_usecase *uc,
1047 struct audio_usecase *new_uc,
1048 snd_device_t new_snd_device)
1049{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301050 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001051
1052 snd_device_t d1 = uc->out_snd_device;
1053 snd_device_t d2 = new_snd_device;
1054
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301055 switch (uc->type) {
1056 case TRANSCODE_LOOPBACK :
1057 a1 = uc->stream.inout->out_config.devices;
1058 a2 = new_uc->stream.inout->out_config.devices;
1059 break;
1060 default :
1061 a1 = uc->stream.out->devices;
1062 a2 = new_uc->stream.out->devices;
1063 break;
1064 }
1065
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001066 // Treat as a special case when a1 and a2 are not disjoint
1067 if ((a1 != a2) && (a1 & a2)) {
1068 snd_device_t d3[2];
1069 int num_devices = 0;
1070 int ret = platform_split_snd_device(platform,
1071 popcount(a1) > 1 ? d1 : d2,
1072 &num_devices,
1073 d3);
1074 if (ret < 0) {
1075 if (ret != -ENOSYS) {
1076 ALOGW("%s failed to split snd_device %d",
1077 __func__,
1078 popcount(a1) > 1 ? d1 : d2);
1079 }
1080 goto end;
1081 }
1082
1083 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1084 // But if it does happen, we need to give priority to d2 if
1085 // the combo devices active on the existing usecase share a backend.
1086 // This is because we cannot have a usecase active on a combo device
1087 // and a new usecase requests one device in this combo pair.
1088 if (platform_check_backends_match(d3[0], d3[1])) {
1089 return d2; // case 5
1090 } else {
1091 return d1; // case 1
1092 }
1093 } else {
1094 if (platform_check_backends_match(d1, d2)) {
1095 return d2; // case 2, 4
1096 } else {
1097 return d1; // case 6, 3
1098 }
1099 }
1100
1101end:
1102 return d2; // return whatever was calculated before.
1103}
1104
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001105static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301106 struct audio_usecase *uc_info,
1107 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001108{
1109 struct listnode *node;
1110 struct audio_usecase *usecase;
1111 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301112 snd_device_t uc_derive_snd_device;
1113 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001114 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001115 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301116 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001117 /*
1118 * This function is to make sure that all the usecases that are active on
1119 * the hardware codec backend are always routed to any one device that is
1120 * handled by the hardware codec.
1121 * For example, if low-latency and deep-buffer usecases are currently active
1122 * on speaker and out_set_parameters(headset) is received on low-latency
1123 * output, then we have to make sure deep-buffer is also switched to headset,
1124 * because of the limitation that both the devices cannot be enabled
1125 * at the same time as they share the same backend.
1126 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001127 /*
1128 * This call is to check if we need to force routing for a particular stream
1129 * If there is a backend configuration change for the device when a
1130 * new stream starts, then ADM needs to be closed and re-opened with the new
1131 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001132 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001133 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001134 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1135 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301136 /* For a2dp device reconfigure all active sessions
1137 * with new AFE encoder format based on a2dp state
1138 */
1139 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1140 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1141 audio_extn_a2dp_is_force_device_switch()) {
1142 force_routing = true;
1143 force_restart_session = true;
1144 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301145 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1146
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001147 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001148 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001149 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001150 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1151 switch_device[i] = false;
1152
1153 list_for_each(node, &adev->usecase_list) {
1154 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001155
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301156 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1157 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301158 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301159 platform_get_snd_device_name(usecase->out_snd_device),
1160 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301161 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1162 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1163 usecase, uc_info, snd_device);
1164 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1165 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1166 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1167 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1168 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1169 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1170 ((force_restart_session) ||
1171 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301172 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1173 __func__, use_case_table[usecase->id],
1174 platform_get_snd_device_name(usecase->out_snd_device));
1175 disable_audio_route(adev, usecase);
1176 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301177 /* Enable existing usecase on derived playback device */
1178 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301179 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301180 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001181 }
1182 }
1183
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301184 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1185 num_uc_to_switch);
1186
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001187 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001188 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001189
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301190 /* Make sure the previous devices to be disabled first and then enable the
1191 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001192 list_for_each(node, &adev->usecase_list) {
1193 usecase = node_to_item(node, struct audio_usecase, list);
1194 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001195 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001196 }
1197 }
1198
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001199 list_for_each(node, &adev->usecase_list) {
1200 usecase = node_to_item(node, struct audio_usecase, list);
1201 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301202 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001203 }
1204 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001205
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001206 /* Re-route all the usecases on the shared backend other than the
1207 specified usecase to new snd devices */
1208 list_for_each(node, &adev->usecase_list) {
1209 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301210 /* Update the out_snd_device only before enabling the audio route */
1211 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301212 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301213 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301214 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301215 use_case_table[usecase->id],
1216 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001217 /* Update voc calibration before enabling VoIP route */
1218 if (usecase->type == VOIP_CALL)
1219 status = platform_switch_voice_call_device_post(adev->platform,
1220 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001221 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301222 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301223 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001224 }
1225 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001226 }
1227}
1228
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301229static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001230 struct audio_usecase *uc_info,
1231 snd_device_t snd_device)
1232{
1233 struct listnode *node;
1234 struct audio_usecase *usecase;
1235 bool switch_device[AUDIO_USECASE_MAX];
1236 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301237 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001238 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001239
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301240 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1241 snd_device);
1242 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301243
1244 /*
1245 * Make sure out devices is checked against out codec backend device and
1246 * also in devices against in codec backend. Checking out device against in
1247 * codec backend or vice versa causes issues.
1248 */
1249 if (uc_info->type == PCM_CAPTURE)
1250 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001251 /*
1252 * This function is to make sure that all the active capture usecases
1253 * are always routed to the same input sound device.
1254 * For example, if audio-record and voice-call usecases are currently
1255 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1256 * is received for voice call then we have to make sure that audio-record
1257 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1258 * because of the limitation that two devices cannot be enabled
1259 * at the same time if they share the same backend.
1260 */
1261 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1262 switch_device[i] = false;
1263
1264 list_for_each(node, &adev->usecase_list) {
1265 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301266 /*
1267 * TODO: Enhance below condition to handle BT sco/USB multi recording
1268 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001269 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001270 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301271 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301272 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301273 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301274 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001275 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001276 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1277 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001278 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001279 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001280 switch_device[usecase->id] = true;
1281 num_uc_to_switch++;
1282 }
1283 }
1284
1285 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001286 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001287
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301288 /* Make sure the previous devices to be disabled first and then enable the
1289 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001290 list_for_each(node, &adev->usecase_list) {
1291 usecase = node_to_item(node, struct audio_usecase, list);
1292 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001293 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001294 }
1295 }
1296
1297 list_for_each(node, &adev->usecase_list) {
1298 usecase = node_to_item(node, struct audio_usecase, list);
1299 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001300 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001301 }
1302 }
1303
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001304 /* Re-route all the usecases on the shared backend other than the
1305 specified usecase to new snd devices */
1306 list_for_each(node, &adev->usecase_list) {
1307 usecase = node_to_item(node, struct audio_usecase, list);
1308 /* Update the in_snd_device only before enabling the audio route */
1309 if (switch_device[usecase->id] ) {
1310 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001311 if (usecase->type != VOICE_CALL) {
1312 /* Update voc calibration before enabling VoIP route */
1313 if (usecase->type == VOIP_CALL)
1314 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001315 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001316 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301317 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001318 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001319 }
1320 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001321 }
1322}
1323
Mingming Yin3a941d42016-02-17 18:08:05 -08001324static void reset_hdmi_sink_caps(struct stream_out *out) {
1325 int i = 0;
1326
1327 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1328 out->supported_channel_masks[i] = 0;
1329 }
1330 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1331 out->supported_formats[i] = 0;
1332 }
1333 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1334 out->supported_sample_rates[i] = 0;
1335 }
1336}
1337
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001338/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001339static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001340{
Mingming Yin3a941d42016-02-17 18:08:05 -08001341 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001342 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001343
Mingming Yin3a941d42016-02-17 18:08:05 -08001344 reset_hdmi_sink_caps(out);
1345
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001346 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001347 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001348 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001349 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001350 }
1351
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001352 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001353 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001354 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001355 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001356 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1357 case 6:
1358 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1359 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1360 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1361 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1362 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1363 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001364 break;
1365 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001366 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001367 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001368 break;
1369 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001370
1371 // check channel format caps
1372 i = 0;
1373 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1374 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1375 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1376 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1377 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1378 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1379 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1380 }
1381
Ben Romberger1aaaf862017-04-06 17:49:46 -07001382 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1383 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1384 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1385 }
1386
Mingming Yin3a941d42016-02-17 18:08:05 -08001387 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1388 ALOGV(":%s HDMI supports DTS format", __func__);
1389 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1390 }
1391
1392 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1393 ALOGV(":%s HDMI supports DTS HD format", __func__);
1394 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1395 }
1396
Naresh Tanniru928f0862017-04-07 16:44:23 -07001397 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1398 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1399 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1400 }
1401
Mingming Yin3a941d42016-02-17 18:08:05 -08001402
1403 // check sample rate caps
1404 i = 0;
1405 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1406 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1407 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1408 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1409 }
1410 }
1411
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001412 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001413}
1414
Alexy Josephb1379942016-01-29 15:49:38 -08001415audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001416 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001417{
1418 struct audio_usecase *usecase;
1419 struct listnode *node;
1420
1421 list_for_each(node, &adev->usecase_list) {
1422 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001423 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001424 ALOGV("%s: usecase id %d", __func__, usecase->id);
1425 return usecase->id;
1426 }
1427 }
1428 return USECASE_INVALID;
1429}
1430
Alexy Josephb1379942016-01-29 15:49:38 -08001431struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001432 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001433{
1434 struct audio_usecase *usecase;
1435 struct listnode *node;
1436
1437 list_for_each(node, &adev->usecase_list) {
1438 usecase = node_to_item(node, struct audio_usecase, list);
1439 if (usecase->id == uc_id)
1440 return usecase;
1441 }
1442 return NULL;
1443}
1444
Dhananjay Kumard4833242016-10-06 22:09:12 +05301445struct stream_in *get_next_active_input(const struct audio_device *adev)
1446{
1447 struct audio_usecase *usecase;
1448 struct listnode *node;
1449
1450 list_for_each_reverse(node, &adev->usecase_list) {
1451 usecase = node_to_item(node, struct audio_usecase, list);
1452 if (usecase->type == PCM_CAPTURE)
1453 return usecase->stream.in;
1454 }
1455 return NULL;
1456}
1457
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301458/*
1459 * is a true native playback active
1460 */
1461bool audio_is_true_native_stream_active(struct audio_device *adev)
1462{
1463 bool active = false;
1464 int i = 0;
1465 struct listnode *node;
1466
1467 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1468 ALOGV("%s:napb: not in true mode or non hdphones device",
1469 __func__);
1470 active = false;
1471 goto exit;
1472 }
1473
1474 list_for_each(node, &adev->usecase_list) {
1475 struct audio_usecase *uc;
1476 uc = node_to_item(node, struct audio_usecase, list);
1477 struct stream_out *curr_out =
1478 (struct stream_out*) uc->stream.out;
1479
1480 if (curr_out && PCM_PLAYBACK == uc->type) {
1481 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1482 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1483 uc->id, curr_out->sample_rate,
1484 curr_out->bit_width,
1485 platform_get_snd_device_name(uc->out_snd_device));
1486
1487 if (is_offload_usecase(uc->id) &&
1488 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1489 active = true;
1490 ALOGD("%s:napb:native stream detected", __func__);
1491 }
1492 }
1493 }
1494exit:
1495 return active;
1496}
1497
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301498/*
1499 * if native DSD playback active
1500 */
1501bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1502{
1503 bool active = false;
1504 struct listnode *node = NULL;
1505 struct audio_usecase *uc = NULL;
1506 struct stream_out *curr_out = NULL;
1507
1508 list_for_each(node, &adev->usecase_list) {
1509 uc = node_to_item(node, struct audio_usecase, list);
1510 curr_out = (struct stream_out*) uc->stream.out;
1511
1512 if (curr_out && PCM_PLAYBACK == uc->type &&
1513 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1514 active = true;
1515 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301516 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301517 }
1518 }
1519 return active;
1520}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301521
1522static bool force_device_switch(struct audio_usecase *usecase)
1523{
1524 bool ret = false;
1525 bool is_it_true_mode = false;
1526
1527 if (is_offload_usecase(usecase->id) &&
1528 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001529 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1530 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1531 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301532 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1533 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1534 (!is_it_true_mode && adev->native_playback_enabled)){
1535 ret = true;
1536 ALOGD("napb: time to toggle native mode");
1537 }
1538 }
1539
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301540 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301541 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1542 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301543 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001544 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301545 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301546 ALOGD("Force a2dp device switch to update new encoder config");
1547 ret = true;
1548 }
1549
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301550 return ret;
1551}
1552
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301553bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1554{
1555 bool ret=false;
1556 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1557 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1558 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1559 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1560 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1561 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1562 ret = true;
1563
1564 return ret;
1565}
1566
1567bool is_a2dp_device(snd_device_t out_snd_device)
1568{
1569 bool ret=false;
1570 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1571 ret = true;
1572
1573 return ret;
1574}
1575
1576bool is_bt_soc_on(struct audio_device *adev)
1577{
1578 struct mixer_ctl *ctl;
1579 char *mixer_ctl_name = "BT SOC status";
1580 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1581 bool bt_soc_status = true;
1582 if (!ctl) {
1583 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1584 __func__, mixer_ctl_name);
1585 /*This is to ensure we dont break targets which dont have the kernel change*/
1586 return true;
1587 }
1588 bt_soc_status = mixer_ctl_get_value(ctl, 0);
1589 ALOGD("BT SOC status: %d",bt_soc_status);
1590 return bt_soc_status;
1591}
1592
1593int out_standby_l(struct audio_stream *stream);
1594
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001595int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001596{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001597 snd_device_t out_snd_device = SND_DEVICE_NONE;
1598 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001599 struct audio_usecase *usecase = NULL;
1600 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001601 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001602 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301603 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001604 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001605 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001606
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301607 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1608
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001609 usecase = get_usecase_from_list(adev, uc_id);
1610 if (usecase == NULL) {
1611 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1612 return -EINVAL;
1613 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001614
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001615 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001616 (usecase->type == VOIP_CALL) ||
1617 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301618 if(usecase->stream.out == NULL) {
1619 ALOGE("%s: stream.out is NULL", __func__);
1620 return -EINVAL;
1621 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001622 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001623 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001624 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001625 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301626 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
1627 if (usecase->stream.inout == NULL) {
1628 ALOGE("%s: stream.inout is NULL", __func__);
1629 return -EINVAL;
1630 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301631 stream_out.devices = usecase->stream.inout->out_config.devices;
1632 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
1633 stream_out.format = usecase->stream.inout->out_config.format;
1634 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
1635 out_snd_device = platform_get_output_snd_device(adev->platform,
1636 &stream_out);
1637 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301638 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001639 } else {
1640 /*
1641 * If the voice call is active, use the sound devices of voice call usecase
1642 * so that it would not result any device switch. All the usecases will
1643 * be switched to new device when select_devices() is called for voice call
1644 * usecase. This is to avoid switching devices for voice call when
1645 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001646 * choose voice call device only if the use case device is
1647 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001648 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001649 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001650 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001651 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001652 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1653 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301654 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1655 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001656 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001657 in_snd_device = vc_usecase->in_snd_device;
1658 out_snd_device = vc_usecase->out_snd_device;
1659 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001660 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001661 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001662 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001663 if ((voip_usecase != NULL) &&
1664 (usecase->type == PCM_PLAYBACK) &&
1665 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001666 out_snd_device_backend_match = platform_check_backends_match(
1667 voip_usecase->out_snd_device,
1668 platform_get_output_snd_device(
1669 adev->platform,
1670 usecase->stream.out));
1671 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001672 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001673 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1674 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001675 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001676 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001677 in_snd_device = voip_usecase->in_snd_device;
1678 out_snd_device = voip_usecase->out_snd_device;
1679 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001680 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001681 hfp_ucid = audio_extn_hfp_get_usecase();
1682 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001683 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001684 in_snd_device = hfp_usecase->in_snd_device;
1685 out_snd_device = hfp_usecase->out_snd_device;
1686 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001687 }
1688 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301689 if (usecase->stream.out == NULL) {
1690 ALOGE("%s: stream.out is NULL", __func__);
1691 return -EINVAL;
1692 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001693 usecase->devices = usecase->stream.out->devices;
1694 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001695 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001696 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001697 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001698 if (usecase->stream.out == adev->primary_output &&
1699 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001700 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001701 select_devices(adev, adev->active_input->usecase);
1702 }
1703 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001704 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301705 if (usecase->stream.in == NULL) {
1706 ALOGE("%s: stream.in is NULL", __func__);
1707 return -EINVAL;
1708 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001709 usecase->devices = usecase->stream.in->device;
1710 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001711 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001712 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001713 if (adev->active_input &&
1714 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301715 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1716 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1717 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001718 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001719 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001720 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1721 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001722 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001723 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001724 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001725 }
1726 }
1727
1728 if (out_snd_device == usecase->out_snd_device &&
1729 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301730
1731 if (!force_device_switch(usecase))
1732 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001733 }
1734
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301735 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
1736 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
1737 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1738 return 0;
1739 }
1740
sangwoobc677242013-08-08 16:53:43 +09001741 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001742 out_snd_device, platform_get_snd_device_name(out_snd_device),
1743 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001744
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745 /*
1746 * Limitation: While in call, to do a device switch we need to disable
1747 * and enable both RX and TX devices though one of them is same as current
1748 * device.
1749 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001750 if ((usecase->type == VOICE_CALL) &&
1751 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1752 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001753 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001754 }
1755
1756 if (((usecase->type == VOICE_CALL) ||
1757 (usecase->type == VOIP_CALL)) &&
1758 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1759 /* Disable sidetone only if voice/voip call already exists */
1760 if (voice_is_call_state_active(adev) ||
1761 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001762 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001763
1764 /* Disable aanc only if voice call exists */
1765 if (voice_is_call_state_active(adev))
1766 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001767 }
1768
Zhou Songc66eb7e2017-08-08 18:29:07 +08001769 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05301770 (!audio_extn_a2dp_is_ready())) {
1771 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08001772 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05301773 }
1774
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001775 /* Disable current sound devices */
1776 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001777 disable_audio_route(adev, usecase);
1778 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001779 }
1780
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001781 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001782 disable_audio_route(adev, usecase);
1783 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784 }
1785
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001786 /* Applicable only on the targets that has external modem.
1787 * New device information should be sent to modem before enabling
1788 * the devices to reduce in-call device switch time.
1789 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001790 if ((usecase->type == VOICE_CALL) &&
1791 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1792 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001793 status = platform_switch_voice_call_enable_device_config(adev->platform,
1794 out_snd_device,
1795 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001796 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001797
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001798 /* Enable new sound devices */
1799 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001800 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301801 if (platform_check_codec_asrc_support(adev->platform))
1802 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001803 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804 }
1805
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001806 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301807 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001808 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001809 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001810
Avinash Vaish71a8b972014-07-24 15:36:33 +05301811 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001812 status = platform_switch_voice_call_device_post(adev->platform,
1813 out_snd_device,
1814 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301815 enable_audio_route_for_voice_usecases(adev, usecase);
1816 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001817
sangwoo170731f2013-06-08 15:36:36 +09001818 usecase->in_snd_device = in_snd_device;
1819 usecase->out_snd_device = out_snd_device;
1820
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301821 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1822 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301823 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001824 if ((24 == usecase->stream.out->bit_width) &&
1825 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1826 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1827 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1828 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1829 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1830 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1831 /*
1832 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1833 * configured device sample rate, if not update the COPP rate to be equal to the
1834 * device sample rate, else open COPP at stream sample rate
1835 */
1836 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1837 usecase->stream.out->sample_rate,
1838 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301839 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1840 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001841 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1842 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1843 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1844 }
1845
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001846 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001847 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001848 audio_extn_gef_notify_device_config(
1849 usecase->stream.out->devices,
1850 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001851 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001852 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001853 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301854 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001855 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001856
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001857 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001858 /* Enable aanc only if voice call exists */
1859 if (voice_is_call_state_active(adev))
1860 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1861
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001862 /* Enable sidetone only if other voice/voip call already exists */
1863 if (voice_is_call_state_active(adev) ||
1864 voice_extn_compress_voip_is_started(adev))
1865 voice_set_sidetone(adev, out_snd_device, true);
1866 }
1867
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001868 /* Applicable only on the targets that has external modem.
1869 * Enable device command should be sent to modem only after
1870 * enabling voice call mixer controls
1871 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001872 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001873 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1874 out_snd_device,
1875 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301876
1877 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
1878
1879 if (usecase->type == VOIP_CALL) {
1880 if (adev->active_input != NULL &&
1881 !adev->active_input->standby) {
1882 if (is_bt_soc_on(adev) == false){
1883 ALOGD("BT SCO MIC disconnected while in connection");
1884 if (adev->active_input->pcm != NULL)
1885 pcm_stop(adev->active_input->pcm);
1886 }
1887 }
1888 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
1889 && usecase->stream.out->started) {
1890 if (is_bt_soc_on(adev) == false) {
1891 ALOGD("BT SCO/A2DP disconnected while in connection");
1892 out_standby_l(&usecase->stream.out->stream.common);
1893 }
1894 }
1895 } else if ((usecase->stream.out != NULL) &&
1896 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
1897 usecase->stream.out->started) {
1898 if (is_bt_soc_on(adev) == false) {
1899 ALOGD("BT SCO/A2dp disconnected while in connection");
1900 out_standby_l(&usecase->stream.out->stream.common);
1901 }
1902 }
1903 }
1904
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301905 ALOGD("%s: done",__func__);
1906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001907 return status;
1908}
1909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910static int stop_input_stream(struct stream_in *in)
1911{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301912 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001913 struct audio_usecase *uc_info;
1914 struct audio_device *adev = in->dev;
1915
Eric Laurent994a6932013-07-17 11:51:42 -07001916 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001917 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001918 uc_info = get_usecase_from_list(adev, in->usecase);
1919 if (uc_info == NULL) {
1920 ALOGE("%s: Could not find the usecase (%d) in the list",
1921 __func__, in->usecase);
1922 return -EINVAL;
1923 }
1924
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001925 /* Close in-call recording streams */
1926 voice_check_and_stop_incall_rec_usecase(adev, in);
1927
Eric Laurent150dbfe2013-02-27 14:31:02 -08001928 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001929 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001930
1931 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001932 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001933
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001934 list_remove(&uc_info->list);
1935 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001936
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001937 adev->active_input = get_next_active_input(adev);
1938
Eric Laurent994a6932013-07-17 11:51:42 -07001939 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001940 return ret;
1941}
1942
1943int start_input_stream(struct stream_in *in)
1944{
1945 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001946 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001947 struct audio_usecase *uc_info;
1948 struct audio_device *adev = in->dev;
1949
Mingming Yin2664a5b2015-09-03 10:53:11 -07001950 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1951 if (get_usecase_from_list(adev, usecase) == NULL)
1952 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301953 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1954 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001955
Naresh Tanniru80659832014-06-04 18:17:56 +05301956
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05301957 if (CARD_STATUS_OFFLINE == in->card_status||
1958 CARD_STATUS_OFFLINE == adev->card_status) {
1959 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301960 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301961 goto error_config;
1962 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301963
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301964 if (audio_is_bluetooth_sco_device(in->device)) {
1965 if (!adev->bt_sco_on) {
1966 ALOGE("%s: SCO profile is not ready, return error", __func__);
1967 ret = -EIO;
1968 goto error_config;
1969 }
1970 }
1971
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001972 /* Check if source matches incall recording usecase criteria */
1973 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1974 if (ret)
1975 goto error_config;
1976 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001977 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1978
1979 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1980 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1981 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001982 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001983 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001984
Eric Laurentb23d5282013-05-14 15:27:20 -07001985 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986 if (in->pcm_device_id < 0) {
1987 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1988 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001989 ret = -EINVAL;
1990 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001992
1993 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001994 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001995
1996 if (!uc_info) {
1997 ret = -ENOMEM;
1998 goto error_config;
1999 }
2000
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001 uc_info->id = in->usecase;
2002 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002003 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002004 uc_info->devices = in->device;
2005 uc_info->in_snd_device = SND_DEVICE_NONE;
2006 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002007
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002008 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302009 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2010 adev->perf_lock_opts,
2011 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002012 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002013
Haynes Mathew George16081042017-05-31 17:16:49 -07002014 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302015 ret = audio_extn_cin_start_input_stream(in);
2016 if (ret)
2017 goto error_open;
2018 else
2019 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002020 }
2021
Haynes Mathew George16081042017-05-31 17:16:49 -07002022 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002023 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002024 ALOGE("%s: pcm stream not ready", __func__);
2025 goto error_open;
2026 }
2027 ret = pcm_start(in->pcm);
2028 if (ret < 0) {
2029 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2030 goto error_open;
2031 }
2032 } else {
2033 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2034 unsigned int pcm_open_retry_count = 0;
2035
2036 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2037 flags |= PCM_MMAP | PCM_NOIRQ;
2038 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2039 } else if (in->realtime) {
2040 flags |= PCM_MMAP | PCM_NOIRQ;
2041 }
2042
2043 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2044 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2045
2046 while (1) {
2047 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
2048 flags, &in->config);
2049 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2050 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2051 if (in->pcm != NULL) {
2052 pcm_close(in->pcm);
2053 in->pcm = NULL;
2054 }
2055 if (pcm_open_retry_count-- == 0) {
2056 ret = -EIO;
2057 goto error_open;
2058 }
2059 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2060 continue;
2061 }
2062 break;
2063 }
2064
2065 ALOGV("%s: pcm_prepare", __func__);
2066 ret = pcm_prepare(in->pcm);
2067 if (ret < 0) {
2068 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2069 pcm_close(in->pcm);
2070 in->pcm = NULL;
2071 goto error_open;
2072 }
2073 register_in_stream(in);
2074 if (in->realtime) {
2075 ret = pcm_start(in->pcm);
2076 if (ret < 0) {
2077 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002078 pcm_close(in->pcm);
2079 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002080 goto error_open;
2081 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002082 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002083 }
2084
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302085done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302086 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002087 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002088
Eric Laurentc8400632013-02-14 19:04:54 -08002089 return ret;
2090
2091error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302092 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002093 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002094error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302095 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302096 /*
2097 * sleep 50ms to allow sufficient time for kernel
2098 * drivers to recover incases like SSR.
2099 */
2100 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002101 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002102
2103 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104}
2105
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002106void lock_input_stream(struct stream_in *in)
2107{
2108 pthread_mutex_lock(&in->pre_lock);
2109 pthread_mutex_lock(&in->lock);
2110 pthread_mutex_unlock(&in->pre_lock);
2111}
2112
2113void lock_output_stream(struct stream_out *out)
2114{
2115 pthread_mutex_lock(&out->pre_lock);
2116 pthread_mutex_lock(&out->lock);
2117 pthread_mutex_unlock(&out->pre_lock);
2118}
2119
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002120/* must be called with out->lock locked */
2121static int send_offload_cmd_l(struct stream_out* out, int command)
2122{
2123 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2124
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002125 if (!cmd) {
2126 ALOGE("failed to allocate mem for command 0x%x", command);
2127 return -ENOMEM;
2128 }
2129
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002130 ALOGVV("%s %d", __func__, command);
2131
2132 cmd->cmd = command;
2133 list_add_tail(&out->offload_cmd_list, &cmd->node);
2134 pthread_cond_signal(&out->offload_cond);
2135 return 0;
2136}
2137
2138/* must be called iwth out->lock locked */
2139static void stop_compressed_output_l(struct stream_out *out)
2140{
2141 out->offload_state = OFFLOAD_STATE_IDLE;
2142 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002143 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002144 if (out->compr != NULL) {
2145 compress_stop(out->compr);
2146 while (out->offload_thread_blocked) {
2147 pthread_cond_wait(&out->cond, &out->lock);
2148 }
2149 }
2150}
2151
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002152bool is_offload_usecase(audio_usecase_t uc_id)
2153{
2154 unsigned int i;
2155 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2156 if (uc_id == offload_usecases[i])
2157 return true;
2158 }
2159 return false;
2160}
2161
Dhananjay Kumarac341582017-02-23 23:42:25 +05302162static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002163{
vivek mehta446c3962015-09-14 10:57:35 -07002164 audio_usecase_t ret_uc = USECASE_INVALID;
2165 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002166 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002167 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302168 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002169 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2170 else
2171 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002172
vivek mehta446c3962015-09-14 10:57:35 -07002173 pthread_mutex_lock(&adev->lock);
2174 if (get_usecase_from_list(adev, ret_uc) != NULL)
2175 ret_uc = USECASE_INVALID;
2176 pthread_mutex_unlock(&adev->lock);
2177
2178 return ret_uc;
2179 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002180
2181 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002182 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2183 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2184 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2185 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002186 break;
2187 }
2188 }
vivek mehta446c3962015-09-14 10:57:35 -07002189
2190 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2191 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002192}
2193
2194static void free_offload_usecase(struct audio_device *adev,
2195 audio_usecase_t uc_id)
2196{
vivek mehta446c3962015-09-14 10:57:35 -07002197 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002198 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002199
2200 if (!adev->multi_offload_enable)
2201 return;
2202
2203 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2204 if (offload_usecases[offload_uc_index] == uc_id) {
2205 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002206 break;
2207 }
2208 }
2209 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2210}
2211
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002212static void *offload_thread_loop(void *context)
2213{
2214 struct stream_out *out = (struct stream_out *) context;
2215 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002216 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002217
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002218 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2219 set_sched_policy(0, SP_FOREGROUND);
2220 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2221
2222 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002223 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002224 for (;;) {
2225 struct offload_cmd *cmd = NULL;
2226 stream_callback_event_t event;
2227 bool send_callback = false;
2228
2229 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2230 __func__, list_empty(&out->offload_cmd_list),
2231 out->offload_state);
2232 if (list_empty(&out->offload_cmd_list)) {
2233 ALOGV("%s SLEEPING", __func__);
2234 pthread_cond_wait(&out->offload_cond, &out->lock);
2235 ALOGV("%s RUNNING", __func__);
2236 continue;
2237 }
2238
2239 item = list_head(&out->offload_cmd_list);
2240 cmd = node_to_item(item, struct offload_cmd, node);
2241 list_remove(item);
2242
2243 ALOGVV("%s STATE %d CMD %d out->compr %p",
2244 __func__, out->offload_state, cmd->cmd, out->compr);
2245
2246 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2247 free(cmd);
2248 break;
2249 }
2250
2251 if (out->compr == NULL) {
2252 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002253 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002254 pthread_cond_signal(&out->cond);
2255 continue;
2256 }
2257 out->offload_thread_blocked = true;
2258 pthread_mutex_unlock(&out->lock);
2259 send_callback = false;
2260 switch(cmd->cmd) {
2261 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002262 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002263 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002264 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002265 send_callback = true;
2266 event = STREAM_CBK_EVENT_WRITE_READY;
2267 break;
2268 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002269 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302270 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002271 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302272 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002273 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302274 if (ret < 0)
2275 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302276 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302277 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002278 compress_drain(out->compr);
2279 else
2280 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302281 if (ret != -ENETRESET) {
2282 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302283 pthread_mutex_lock(&out->lock);
2284 out->send_new_metadata = 1;
2285 out->send_next_track_params = true;
2286 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302287 event = STREAM_CBK_EVENT_DRAIN_READY;
2288 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2289 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302290 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002291 break;
2292 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002293 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002294 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002295 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002296 send_callback = true;
2297 event = STREAM_CBK_EVENT_DRAIN_READY;
2298 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302299 case OFFLOAD_CMD_ERROR:
2300 ALOGD("copl(%p): sending error callback to AF", out);
2301 send_callback = true;
2302 event = STREAM_CBK_EVENT_ERROR;
2303 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002304 default:
2305 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2306 break;
2307 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002308 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002309 out->offload_thread_blocked = false;
2310 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002311 if (send_callback && out->client_callback) {
2312 ALOGVV("%s: sending client_callback event %d", __func__, event);
2313 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002314 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002315 free(cmd);
2316 }
2317
2318 pthread_cond_signal(&out->cond);
2319 while (!list_empty(&out->offload_cmd_list)) {
2320 item = list_head(&out->offload_cmd_list);
2321 list_remove(item);
2322 free(node_to_item(item, struct offload_cmd, node));
2323 }
2324 pthread_mutex_unlock(&out->lock);
2325
2326 return NULL;
2327}
2328
2329static int create_offload_callback_thread(struct stream_out *out)
2330{
2331 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2332 list_init(&out->offload_cmd_list);
2333 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2334 offload_thread_loop, out);
2335 return 0;
2336}
2337
2338static int destroy_offload_callback_thread(struct stream_out *out)
2339{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002340 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002341 stop_compressed_output_l(out);
2342 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2343
2344 pthread_mutex_unlock(&out->lock);
2345 pthread_join(out->offload_thread, (void **) NULL);
2346 pthread_cond_destroy(&out->offload_cond);
2347
2348 return 0;
2349}
2350
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351static int stop_output_stream(struct stream_out *out)
2352{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302353 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002354 struct audio_usecase *uc_info;
2355 struct audio_device *adev = out->dev;
2356
Eric Laurent994a6932013-07-17 11:51:42 -07002357 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002358 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002359 uc_info = get_usecase_from_list(adev, out->usecase);
2360 if (uc_info == NULL) {
2361 ALOGE("%s: Could not find the usecase (%d) in the list",
2362 __func__, out->usecase);
2363 return -EINVAL;
2364 }
2365
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002366 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302367 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002368 if (adev->visualizer_stop_output != NULL)
2369 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002370
2371 audio_extn_dts_remove_state_notifier_node(out->usecase);
2372
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002373 if (adev->offload_effects_stop_output != NULL)
2374 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2375 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002376
Eric Laurent150dbfe2013-02-27 14:31:02 -08002377 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002378 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002379
2380 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002381 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002383 list_remove(&uc_info->list);
2384 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302385 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002386 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302387 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002388 ALOGV("Disable passthrough , reset mixer to pcm");
2389 /* NO_PASSTHROUGH */
2390 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002391 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002392 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2393 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002394
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302395 /* Must be called after removing the usecase from list */
2396 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302397 audio_extn_keep_alive_start();
2398
Naresh Tanniru85819452017-05-04 18:55:45 -07002399 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
2400 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2401 if (ret < 0)
2402 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2403 }
2404
Eric Laurent994a6932013-07-17 11:51:42 -07002405 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002406 return ret;
2407}
2408
2409int start_output_stream(struct stream_out *out)
2410{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002411 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412 struct audio_usecase *uc_info;
2413 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002414 char mixer_ctl_name[128];
2415 struct mixer_ctl *ctl = NULL;
2416 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302417 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002418
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002419 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2420 ret = -EINVAL;
2421 goto error_config;
2422 }
2423
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302424 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2425 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2426 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302427
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302428 if (CARD_STATUS_OFFLINE == out->card_status ||
2429 CARD_STATUS_OFFLINE == adev->card_status) {
2430 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302431 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302432 goto error_config;
2433 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302434
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302435 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2436 if (!audio_extn_a2dp_is_ready()) {
2437 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302438 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302439 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302440 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2441 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2442 ret = -EAGAIN;
2443 goto error_config;
2444 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302445 }
2446 }
2447 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302448 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2449 if (!adev->bt_sco_on) {
2450 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2451 //combo usecase just by pass a2dp
2452 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
2453 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2454 } else {
2455 ALOGE("%s: SCO profile is not ready, return error", __func__);
2456 ret = -EAGAIN;
2457 goto error_config;
2458 }
2459 }
2460 }
2461
Eric Laurentb23d5282013-05-14 15:27:20 -07002462 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002463 if (out->pcm_device_id < 0) {
2464 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2465 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002466 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002467 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002468 }
2469
2470 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002471
2472 if (!uc_info) {
2473 ret = -ENOMEM;
2474 goto error_config;
2475 }
2476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477 uc_info->id = out->usecase;
2478 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002479 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002480 uc_info->devices = out->devices;
2481 uc_info->in_snd_device = SND_DEVICE_NONE;
2482 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002483 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302485 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2486 adev->perf_lock_opts,
2487 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302488
2489 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2490 audio_extn_keep_alive_stop();
2491 if (audio_extn_passthru_is_enabled() &&
2492 audio_extn_passthru_is_passthrough_stream(out)) {
2493 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302494 }
2495 }
2496
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302497 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2498 (!audio_extn_a2dp_is_ready())) {
2499 if (!a2dp_combo) {
2500 check_a2dp_restore_l(adev, out, false);
2501 } else {
2502 audio_devices_t dev = out->devices;
2503 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2504 select_devices(adev, out->usecase);
2505 out->devices = dev;
2506 }
2507 } else {
2508 select_devices(adev, out->usecase);
2509 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002510
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002511 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2512 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07002513
2514 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2515 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2516 ALOGE("%s: pcm stream not ready", __func__);
2517 goto error_open;
2518 }
2519 ret = pcm_start(out->pcm);
2520 if (ret < 0) {
2521 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2522 goto error_open;
2523 }
2524 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002525 unsigned int flags = PCM_OUT;
2526 unsigned int pcm_open_retry_count = 0;
2527 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2528 flags |= PCM_MMAP | PCM_NOIRQ;
2529 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002530 } else if (out->realtime) {
2531 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002532 } else
2533 flags |= PCM_MONOTONIC;
2534
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002535 if ((adev->vr_audio_mode_enabled) &&
2536 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2537 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2538 "PCM_Dev %d Topology", out->pcm_device_id);
2539 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2540 if (!ctl) {
2541 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2542 __func__, mixer_ctl_name);
2543 } else {
2544 //if success use ULLPP
2545 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2546 __func__, mixer_ctl_name, out->pcm_device_id);
2547 //There is a still a possibility that some sessions
2548 // that request for FAST|RAW when 3D audio is active
2549 //can go through ULLPP. Ideally we expects apps to
2550 //listen to audio focus and stop concurrent playback
2551 //Also, we will look for mode flag (voice_in_communication)
2552 //before enabling the realtime flag.
2553 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2554 }
2555 }
2556
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002557 while (1) {
2558 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2559 flags, &out->config);
2560 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2561 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2562 if (out->pcm != NULL) {
2563 pcm_close(out->pcm);
2564 out->pcm = NULL;
2565 }
2566 if (pcm_open_retry_count-- == 0) {
2567 ret = -EIO;
2568 goto error_open;
2569 }
2570 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2571 continue;
2572 }
2573 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002574 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002575
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002576 ALOGV("%s: pcm_prepare", __func__);
2577 if (pcm_is_ready(out->pcm)) {
2578 ret = pcm_prepare(out->pcm);
2579 if (ret < 0) {
2580 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2581 pcm_close(out->pcm);
2582 out->pcm = NULL;
2583 goto error_open;
2584 }
2585 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302586 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302587 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
2588
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002589 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002590 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302591 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002593 out->compr = compress_open(adev->snd_card,
2594 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002595 COMPRESS_IN, &out->compr_config);
2596 if (out->compr && !is_compress_ready(out->compr)) {
2597 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2598 compress_close(out->compr);
2599 out->compr = NULL;
2600 ret = -EIO;
2601 goto error_open;
2602 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302603 /* compress_open sends params of the track, so reset the flag here */
2604 out->is_compr_metadata_avail = false;
2605
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002606 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002607 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002608
Fred Oh3f43e742015-03-04 18:42:34 -08002609 /* Since small bufs uses blocking writes, a write will be blocked
2610 for the default max poll time (20s) in the event of an SSR.
2611 Reduce the poll time to observe and deal with SSR faster.
2612 */
Ashish Jain5106d362016-05-11 19:23:33 +05302613 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002614 compress_set_max_poll_wait(out->compr, 1000);
2615 }
2616
Manish Dewangan69426c82017-01-30 17:35:36 +05302617 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302618 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05302619
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002620 audio_extn_dts_create_state_notifier_node(out->usecase);
2621 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2622 popcount(out->channel_mask),
2623 out->playback_started);
2624
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002625#ifdef DS1_DOLBY_DDP_ENABLED
2626 if (audio_extn_is_dolby_format(out->format))
2627 audio_extn_dolby_send_ddp_endp_params(adev);
2628#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302629 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2630 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002631 if (adev->visualizer_start_output != NULL)
2632 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2633 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302634 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002635 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002636 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002637 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002638
2639 if (ret == 0) {
2640 register_out_stream(out);
2641 if (out->realtime) {
2642 ret = pcm_start(out->pcm);
2643 if (ret < 0)
2644 goto error_open;
2645 }
2646 }
2647
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302648 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002649 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002650
Naresh Tanniru85819452017-05-04 18:55:45 -07002651 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07002652 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07002653 if (ret < 0)
2654 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
2655 }
2656
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002657 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002658error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302659 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002661error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302662 /*
2663 * sleep 50ms to allow sufficient time for kernel
2664 * drivers to recover incases like SSR.
2665 */
2666 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002667 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668}
2669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670static int check_input_parameters(uint32_t sample_rate,
2671 audio_format_t format,
2672 int channel_count)
2673{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002674 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302676 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2677 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2678 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002679 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302680 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002681
2682 switch (channel_count) {
2683 case 1:
2684 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302685 case 3:
2686 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002687 case 6:
2688 break;
2689 default:
2690 ret = -EINVAL;
2691 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692
2693 switch (sample_rate) {
2694 case 8000:
2695 case 11025:
2696 case 12000:
2697 case 16000:
2698 case 22050:
2699 case 24000:
2700 case 32000:
2701 case 44100:
2702 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302703 case 96000:
2704 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002705 break;
2706 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002707 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708 }
2709
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002710 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711}
2712
2713static size_t get_input_buffer_size(uint32_t sample_rate,
2714 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002715 int channel_count,
2716 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717{
2718 size_t size = 0;
2719
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002720 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2721 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002723 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002724 if (is_low_latency)
2725 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302726
2727 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002729 /* make sure the size is multiple of 32 bytes
2730 * At 48 kHz mono 16-bit PCM:
2731 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2732 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2733 */
2734 size += 0x1f;
2735 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002736
2737 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738}
2739
Ashish Jain058165c2016-09-28 23:18:48 +05302740static size_t get_output_period_size(uint32_t sample_rate,
2741 audio_format_t format,
2742 int channel_count,
2743 int duration /*in millisecs*/)
2744{
2745 size_t size = 0;
2746 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2747
2748 if ((duration == 0) || (sample_rate == 0) ||
2749 (bytes_per_sample == 0) || (channel_count == 0)) {
2750 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2751 bytes_per_sample, channel_count);
2752 return -EINVAL;
2753 }
2754
2755 size = (sample_rate *
2756 duration *
2757 bytes_per_sample *
2758 channel_count) / 1000;
2759 /*
2760 * To have same PCM samples for all channels, the buffer size requires to
2761 * be multiple of (number of channels * bytes per sample)
2762 * For writes to succeed, the buffer must be written at address which is multiple of 32
2763 */
2764 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2765
2766 return (size/(channel_count * bytes_per_sample));
2767}
2768
Ashish Jain5106d362016-05-11 19:23:33 +05302769static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2770{
2771 uint64_t actual_frames_rendered = 0;
2772 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2773
2774 /* This adjustment accounts for buffering after app processor.
2775 * It is based on estimated DSP latency per use case, rather than exact.
2776 */
2777 int64_t platform_latency = platform_render_latency(out->usecase) *
2778 out->sample_rate / 1000000LL;
2779
2780 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2781 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2782 * hence only estimate.
2783 */
2784 int64_t signed_frames = out->written - kernel_buffer_size;
2785
2786 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2787
2788 if (signed_frames > 0)
2789 actual_frames_rendered = signed_frames;
2790
2791 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2792 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2793 (long long int)out->written, (int)kernel_buffer_size,
2794 audio_bytes_per_sample(out->compr_config.codec->format),
2795 popcount(out->channel_mask));
2796
2797 return actual_frames_rendered;
2798}
2799
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002800static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2801{
2802 struct stream_out *out = (struct stream_out *)stream;
2803
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002804 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002805}
2806
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002807static int out_set_sample_rate(struct audio_stream *stream __unused,
2808 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809{
2810 return -ENOSYS;
2811}
2812
2813static size_t out_get_buffer_size(const struct audio_stream *stream)
2814{
2815 struct stream_out *out = (struct stream_out *)stream;
2816
Naresh Tanniruee3499a2017-01-05 14:05:35 +05302817 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2818 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
2819 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
2820 else
2821 return out->compr_config.fragment_size;
2822 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002823 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07002824 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
2825 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 +05302826 else if (is_offload_usecase(out->usecase) &&
2827 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302828 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002829
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002830 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002831 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832}
2833
2834static uint32_t out_get_channels(const struct audio_stream *stream)
2835{
2836 struct stream_out *out = (struct stream_out *)stream;
2837
2838 return out->channel_mask;
2839}
2840
2841static audio_format_t out_get_format(const struct audio_stream *stream)
2842{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002843 struct stream_out *out = (struct stream_out *)stream;
2844
2845 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002846}
2847
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002848static int out_set_format(struct audio_stream *stream __unused,
2849 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002850{
2851 return -ENOSYS;
2852}
2853
2854static int out_standby(struct audio_stream *stream)
2855{
2856 struct stream_out *out = (struct stream_out *)stream;
2857 struct audio_device *adev = out->dev;
kunleiza9d11682017-08-04 14:14:09 +08002858 struct audio_usecase *uc_info;
2859 struct listnode *node;
Haynes Mathew George16081042017-05-31 17:16:49 -07002860 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002861
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302862 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2863 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002864
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002865 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002866 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002867 if (adev->adm_deregister_stream)
2868 adev->adm_deregister_stream(adev->adm_data, out->handle);
2869
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002870 if (is_offload_usecase(out->usecase))
2871 stop_compressed_output_l(out);
2872
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002873 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002874 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002875 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2876 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302877 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08002878 pthread_mutex_unlock(&adev->lock);
2879 pthread_mutex_unlock(&out->lock);
2880 ALOGD("VOIP output entered standby");
2881 return 0;
2882 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002883 if (out->pcm) {
2884 pcm_close(out->pcm);
2885 out->pcm = NULL;
2886 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002887 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2888 do_stop = out->playback_started;
2889 out->playback_started = false;
2890 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002891 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002892 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302893 out->send_next_track_params = false;
2894 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002895 out->gapless_mdata.encoder_delay = 0;
2896 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002897 if (out->compr != NULL) {
2898 compress_close(out->compr);
2899 out->compr = NULL;
2900 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002901 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002902 if (do_stop) {
2903 stop_output_stream(out);
2904 }
kunleiza9d11682017-08-04 14:14:09 +08002905 //restore output device for active usecase when current snd device and output device mismatch
2906 list_for_each(node, &adev->usecase_list) {
2907 uc_info = node_to_item(node, struct audio_usecase, list);
2908 if ((uc_info->type == PCM_PLAYBACK) &&
2909 (uc_info->out_snd_device != platform_get_output_snd_device(adev->platform, uc_info->stream.out)))
2910 select_devices(adev, uc_info->id);
2911 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002912 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002913 }
2914 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302915 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002916 return 0;
2917}
2918
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302919static int out_on_error(struct audio_stream *stream)
2920{
2921 struct stream_out *out = (struct stream_out *)stream;
2922 bool do_standby = false;
2923
2924 lock_output_stream(out);
2925 if (!out->standby) {
2926 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2927 stop_compressed_output_l(out);
2928 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2929 } else
2930 do_standby = true;
2931 }
2932 pthread_mutex_unlock(&out->lock);
2933
2934 if (do_standby)
2935 return out_standby(&out->stream.common);
2936
2937 return 0;
2938}
2939
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302940/*
2941 *standby implementation without locks, assumes that the callee already
2942 *has taken adev and out lock.
2943 */
2944int out_standby_l(struct audio_stream *stream)
2945{
2946 struct stream_out *out = (struct stream_out *)stream;
2947 struct audio_device *adev = out->dev;
2948
2949 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2950 stream, out->usecase, use_case_table[out->usecase]);
2951
2952 if (!out->standby) {
2953 if (adev->adm_deregister_stream)
2954 adev->adm_deregister_stream(adev->adm_data, out->handle);
2955
2956 if (is_offload_usecase(out->usecase))
2957 stop_compressed_output_l(out);
2958
2959 out->standby = true;
2960 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2961 voice_extn_compress_voip_close_output_stream(stream);
2962 out->started = 0;
2963 ALOGD("VOIP output entered standby");
2964 return 0;
2965 } else if (!is_offload_usecase(out->usecase)) {
2966 if (out->pcm) {
2967 pcm_close(out->pcm);
2968 out->pcm = NULL;
2969 }
2970 } else {
2971 ALOGD("copl(%p):standby", out);
2972 out->send_next_track_params = false;
2973 out->is_compr_metadata_avail = false;
2974 out->gapless_mdata.encoder_delay = 0;
2975 out->gapless_mdata.encoder_padding = 0;
2976 if (out->compr != NULL) {
2977 compress_close(out->compr);
2978 out->compr = NULL;
2979 }
2980 }
2981 stop_output_stream(out);
2982 }
2983 ALOGD("%s: exit", __func__);
2984 return 0;
2985}
2986
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002987static int out_dump(const struct audio_stream *stream __unused,
2988 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989{
2990 return 0;
2991}
2992
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002993static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2994{
2995 int ret = 0;
2996 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002997
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002998 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002999 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003000 return -EINVAL;
3001 }
3002
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303003 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003004
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003005 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3006 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303007 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003008 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003009 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3010 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303011 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003012 }
3013
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003014 ALOGV("%s new encoder delay %u and padding %u", __func__,
3015 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3016
3017 return 0;
3018}
3019
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003020static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3021{
3022 return out == adev->primary_output || out == adev->voice_tx_output;
3023}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003024
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303025// note: this call is safe only if the stream_cb is
3026// removed first in close_output_stream (as is done now).
3027static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3028{
3029 if (!stream || !parms)
3030 return;
3031
3032 struct stream_out *out = (struct stream_out *)stream;
3033 struct audio_device *adev = out->dev;
3034
3035 card_status_t status;
3036 int card;
3037 if (parse_snd_card_status(parms, &card, &status) < 0)
3038 return;
3039
3040 pthread_mutex_lock(&adev->lock);
3041 bool valid_cb = (card == adev->snd_card);
3042 pthread_mutex_unlock(&adev->lock);
3043
3044 if (!valid_cb)
3045 return;
3046
3047 lock_output_stream(out);
3048 if (out->card_status != status)
3049 out->card_status = status;
3050 pthread_mutex_unlock(&out->lock);
3051
3052 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3053 use_case_table[out->usecase],
3054 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3055
3056 if (status == CARD_STATUS_OFFLINE)
3057 out_on_error(stream);
3058
3059 return;
3060}
3061
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3063{
3064 struct stream_out *out = (struct stream_out *)stream;
3065 struct audio_device *adev = out->dev;
3066 struct str_parms *parms;
3067 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003068 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303069 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003070
sangwoobc677242013-08-08 16:53:43 +09003071 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003072 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303074 if (!parms)
3075 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003076 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3077 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003079 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003080 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003082 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003083 * When HDMI cable is unplugged the music playback is paused and
3084 * the policy manager sends routing=0. But the audioflinger continues
3085 * to write data until standby time (3sec). As the HDMI core is
3086 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003087 * Avoid this by routing audio to speaker until standby.
3088 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003089 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3090 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303091 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003092 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3093 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003094 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303095 /*
3096 * When A2DP is disconnected the
3097 * music playback is paused and the policy manager sends routing=0
3098 * But the audioflingercontinues to write data until standby time
3099 * (3sec). As BT is turned off, the write gets blocked.
3100 * Avoid this by routing audio to speaker until standby.
3101 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003102 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303103 (val == AUDIO_DEVICE_NONE)) {
3104 val = AUDIO_DEVICE_OUT_SPEAKER;
3105 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303106 /* To avoid a2dp to sco overlapping / BT device improper state
3107 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303108 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303109 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3110 if (!audio_extn_a2dp_is_ready()) {
3111 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3112 //combo usecase just by pass a2dp
3113 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303114 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303115 } else {
3116 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3117 /* update device to a2dp and don't route as BT returned error
3118 * However it is still possible a2dp routing called because
3119 * of current active device disconnection (like wired headset)
3120 */
3121 out->devices = val;
3122 pthread_mutex_unlock(&out->lock);
3123 pthread_mutex_unlock(&adev->lock);
3124 goto error;
3125 }
3126 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303127 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003128 /*
3129 * select_devices() call below switches all the usecases on the same
3130 * backend to the new device. Refer to check_usecases_codec_backend() in
3131 * the select_devices(). But how do we undo this?
3132 *
3133 * For example, music playback is active on headset (deep-buffer usecase)
3134 * and if we go to ringtones and select a ringtone, low-latency usecase
3135 * will be started on headset+speaker. As we can't enable headset+speaker
3136 * and headset devices at the same time, select_devices() switches the music
3137 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3138 * So when the ringtone playback is completed, how do we undo the same?
3139 *
3140 * We are relying on the out_set_parameters() call on deep-buffer output,
3141 * once the ringtone playback is ended.
3142 * NOTE: We should not check if the current devices are same as new devices.
3143 * Because select_devices() must be called to switch back the music
3144 * playback to headset.
3145 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003146 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003147 audio_devices_t new_dev = val;
3148 bool same_dev = out->devices == new_dev;
3149 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003150
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003151 if (output_drives_call(adev, out)) {
3152 if(!voice_is_in_call(adev)) {
3153 if (adev->mode == AUDIO_MODE_IN_CALL) {
3154 adev->current_call_output = out;
3155 ret = voice_start_call(adev);
3156 }
3157 } else {
3158 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003159 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003160 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003161 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003162
3163 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003164 if (!same_dev) {
3165 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303166 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3167 adev->perf_lock_opts,
3168 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003169 if (adev->adm_on_routing_change)
3170 adev->adm_on_routing_change(adev->adm_data,
3171 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003172 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303173 if (!bypass_a2dp) {
3174 select_devices(adev, out->usecase);
3175 } else {
3176 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3177 select_devices(adev, out->usecase);
3178 out->devices = new_dev;
3179 }
Sudheer Papothi80266982016-08-16 02:36:18 +05303180 if (!same_dev)
3181 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303182 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3183 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003184 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303185 pthread_mutex_lock(&out->compr_mute_lock);
3186 out->a2dp_compress_mute = false;
3187 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3188 pthread_mutex_unlock(&out->compr_mute_lock);
3189 }
3190
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003191 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003192 }
3193
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003195 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003197
3198 if (out == adev->primary_output) {
3199 pthread_mutex_lock(&adev->lock);
3200 audio_extn_set_parameters(adev, parms);
3201 pthread_mutex_unlock(&adev->lock);
3202 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003203 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003204 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003205 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003206
3207 audio_extn_dts_create_state_notifier_node(out->usecase);
3208 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3209 popcount(out->channel_mask),
3210 out->playback_started);
3211
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003212 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003213 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003214
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303215 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3216 if (err >= 0) {
3217 strlcpy(out->profile, value, sizeof(out->profile));
3218 ALOGV("updating stream profile with value '%s'", out->profile);
3219 lock_output_stream(out);
3220 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3221 &adev->streams_output_cfg_list,
3222 out->devices, out->flags, out->format,
3223 out->sample_rate, out->bit_width,
3224 out->channel_mask, out->profile,
3225 &out->app_type_cfg);
3226 pthread_mutex_unlock(&out->lock);
3227 }
3228
Alexy Joseph98988832017-01-13 14:56:59 -08003229 //suspend, resume handling block
3230 if (out->dynamic_pm_qos_enabled) {
3231 //check suspend parameter only for low latency and if the property
3232 //is enabled
3233 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3234 ALOGI("%s: got suspend_playback %s", __func__, value);
3235 lock_output_stream(out);
3236 if (!strncmp(value, "false", 5)) {
3237 //suspend_playback=false is supposed to set QOS value back to 75%
3238 //the mixer control sent with value Enable will achieve that
3239 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3240 } else if (!strncmp (value, "true", 4)) {
3241 //suspend_playback=true is supposed to remove QOS value
3242 //resetting the mixer control will set the default value
3243 //for the mixer control which is Disable and this removes the QOS vote
3244 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3245 } else {
3246 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3247 " got %s", __func__, value);
3248 ret = -1;
3249 }
3250
3251 if (ret != 0) {
3252 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3253 __func__, out->pm_qos_mixer_path, ret);
3254 }
3255
3256 pthread_mutex_unlock(&out->lock);
3257 }
3258 }
3259 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303261error:
Eric Laurent994a6932013-07-17 11:51:42 -07003262 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263 return ret;
3264}
3265
3266static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3267{
3268 struct stream_out *out = (struct stream_out *)stream;
3269 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003270 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271 char value[256];
3272 struct str_parms *reply = str_parms_create();
3273 size_t i, j;
3274 int ret;
3275 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003276
3277 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003278 if (reply) {
3279 str_parms_destroy(reply);
3280 }
3281 if (query) {
3282 str_parms_destroy(query);
3283 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003284 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
3285 return NULL;
3286 }
3287
Eric Laurent994a6932013-07-17 11:51:42 -07003288 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003289 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
3290 if (ret >= 0) {
3291 value[0] = '\0';
3292 i = 0;
3293 while (out->supported_channel_masks[i] != 0) {
3294 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
3295 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
3296 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003297 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003299 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 first = false;
3301 break;
3302 }
3303 }
3304 i++;
3305 }
3306 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3307 str = str_parms_to_str(reply);
3308 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003309 voice_extn_out_get_parameters(out, query, reply);
3310 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003312
Alexy Joseph62142aa2015-11-16 15:10:34 -08003313
3314 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
3315 if (ret >= 0) {
3316 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05303317 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
3318 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08003319 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303320 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003321 } else {
3322 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05303323 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003324 }
3325 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003326 if (str)
3327 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08003328 str = str_parms_to_str(reply);
3329 }
3330
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003331 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
3332 if (ret >= 0) {
3333 value[0] = '\0';
3334 i = 0;
3335 first = true;
3336 while (out->supported_formats[i] != 0) {
3337 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
3338 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
3339 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003340 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003341 }
3342 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
3343 first = false;
3344 break;
3345 }
3346 }
3347 i++;
3348 }
3349 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003350 if (str)
3351 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003352 str = str_parms_to_str(reply);
3353 }
Mingming Yin3a941d42016-02-17 18:08:05 -08003354
3355 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
3356 if (ret >= 0) {
3357 value[0] = '\0';
3358 i = 0;
3359 first = true;
3360 while (out->supported_sample_rates[i] != 0) {
3361 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
3362 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
3363 if (!first) {
3364 strlcat(value, "|", sizeof(value));
3365 }
3366 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
3367 first = false;
3368 break;
3369 }
3370 }
3371 i++;
3372 }
3373 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
3374 if (str)
3375 free(str);
3376 str = str_parms_to_str(reply);
3377 }
3378
Alexy Joseph98988832017-01-13 14:56:59 -08003379 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
3380 //only low latency track supports suspend_resume
3381 str_parms_add_int(reply, "supports_hw_suspend",
3382 (out->dynamic_pm_qos_enabled));
3383 if (str)
3384 free(str);
3385 str = str_parms_to_str(reply);
3386 }
3387
3388
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389 str_parms_destroy(query);
3390 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003391 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392 return str;
3393}
3394
3395static uint32_t out_get_latency(const struct audio_stream_out *stream)
3396{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003397 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003398 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08003399 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400
Alexy Josephaa54c872014-12-03 02:46:47 -08003401 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05303402 lock_output_stream(out);
3403 latency = audio_extn_utils_compress_get_dsp_latency(out);
3404 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07003405 } else if ((out->realtime) ||
3406 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003407 // since the buffer won't be filled up faster than realtime,
3408 // return a smaller number
3409 if (out->config.rate)
3410 period_ms = (out->af_period_multiplier * out->config.period_size *
3411 1000) / (out->config.rate);
3412 else
3413 period_ms = 0;
3414 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003415 } else {
3416 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003417 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003418 }
3419
yidongh0515e042017-07-06 15:00:34 +08003420 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003421 latency += audio_extn_a2dp_get_encoder_latency();
3422
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303423 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003424 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425}
3426
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303427static float AmpToDb(float amplification)
3428{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303429 float db = DSD_VOLUME_MIN_DB;
3430 if (amplification > 0) {
3431 db = 20 * log10(amplification);
3432 if(db < DSD_VOLUME_MIN_DB)
3433 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303434 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303435 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303436}
3437
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303438static int out_set_compr_volume(struct audio_stream_out *stream, float left,
3439 float right)
3440{
3441 struct stream_out *out = (struct stream_out *)stream;
3442 int volume[2];
3443 char mixer_ctl_name[128];
3444 struct audio_device *adev = out->dev;
3445 struct mixer_ctl *ctl;
3446 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3447 PCM_PLAYBACK);
3448
3449 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3450 "Compress Playback %d Volume", pcm_device_id);
3451 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3452 if (!ctl) {
3453 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3454 __func__, mixer_ctl_name);
3455 return -EINVAL;
3456 }
3457 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
3458 __func__, mixer_ctl_name, left, right);
3459 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3460 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3461 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3462
3463 return 0;
3464}
3465
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466static int out_set_volume(struct audio_stream_out *stream, float left,
3467 float right)
3468{
Eric Laurenta9024de2013-04-04 09:19:12 -07003469 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003470 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303471 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003472
Eric Laurenta9024de2013-04-04 09:19:12 -07003473 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3474 /* only take left channel into account: the API is for stereo anyway */
3475 out->muted = (left == 0.0f);
3476 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003477 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303478 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003479 /*
3480 * Set mute or umute on HDMI passthrough stream.
3481 * Only take left channel into account.
3482 * Mute is 0 and unmute 1
3483 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303484 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303485 } else if (out->format == AUDIO_FORMAT_DSD){
3486 char mixer_ctl_name[128] = "DSD Volume";
3487 struct audio_device *adev = out->dev;
3488 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3489
3490 if (!ctl) {
3491 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3492 __func__, mixer_ctl_name);
3493 return -EINVAL;
3494 }
3495 volume[0] = (int)(AmpToDb(left));
3496 volume[1] = (int)(AmpToDb(right));
3497 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3498 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003499 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303500 pthread_mutex_lock(&out->compr_mute_lock);
3501 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3502 if (!out->a2dp_compress_mute)
3503 ret = out_set_compr_volume(stream, left, right);
3504 out->volume_l = left;
3505 out->volume_r = right;
3506 pthread_mutex_unlock(&out->compr_mute_lock);
3507 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003508 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003509 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
3510 char mixer_ctl_name[] = "App Type Gain";
3511 struct audio_device *adev = out->dev;
3512 struct mixer_ctl *ctl;
3513 uint32_t set_values[4];
3514
3515 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3516 if (!ctl) {
3517 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3518 __func__, mixer_ctl_name);
3519 return -EINVAL;
3520 }
3521
3522 set_values[0] = 0; //0: Rx Session 1:Tx Session
3523 set_values[1] = out->app_type_cfg.app_type;
3524 set_values[2] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3525 set_values[3] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3526
3527 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
3528 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003529 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 return -ENOSYS;
3532}
3533
3534static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3535 size_t bytes)
3536{
3537 struct stream_out *out = (struct stream_out *)stream;
3538 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003539 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003541 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303542
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303543 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003544
Dhananjay Kumarac341582017-02-23 23:42:25 +05303545 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303546 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303547 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3548 pthread_mutex_unlock(&out->lock);
3549 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303550 } else {
3551 /* increase written size during SSR to avoid mismatch
3552 * with the written frames count in AF
3553 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003554 // bytes per frame
3555 size_t bpf = audio_bytes_per_sample(out->format) *
3556 audio_channel_count_from_out_mask(out->channel_mask);
3557 if (bpf != 0)
3558 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303559 ALOGD(" %s: sound card is not active/SSR state", __func__);
3560 ret= -EIO;
3561 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303562 }
3563 }
3564
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303565 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303566 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ben Romberger4863ed72017-06-23 14:25:27 -07003567 if ((audio_bytes_per_sample(out->format) != 0) && (out->config.channels != 0))
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303568 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3569 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303570 goto exit;
3571 }
3572
Haynes Mathew George16081042017-05-31 17:16:49 -07003573 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3574 ret = -EINVAL;
3575 goto exit;
3576 }
3577
Manish Dewangan37864bc2017-06-09 12:28:37 +05303578 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3579 /*ADD audio_extn_passthru_is_passthrough_stream(out) check*/
3580 if ((audio_extn_passthru_is_enabled()) &&
3581 (!out->is_iec61937_info_available)) {
3582 audio_extn_passthru_update_stream_configuration(adev, out,
3583 buffer, bytes);
3584 out->is_iec61937_info_available = true;
3585 }
3586 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303587
3588 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3589 (audio_extn_a2dp_is_suspended())) {
3590 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
3591 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3592 size_t bpf = audio_bytes_per_sample(out->format) *
3593 audio_channel_count_from_out_mask(out->channel_mask);
3594 if (bpf != 0)
3595 out->written += bytes / bpf;
3596 ret = -EIO;
3597 goto exit;
3598 }
3599 }
3600 }
3601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003602 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003603 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003604 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003605 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3606 ret = voice_extn_compress_voip_start_output_stream(out);
3607 else
3608 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003609 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003610 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003612 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003613 goto exit;
3614 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303615 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003616 if (last_known_cal_step != -1) {
3617 ALOGD("%s: retry previous failed cal level set", __func__);
3618 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05303619 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003620 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003621 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622
Ashish Jain81eb2a82015-05-13 10:52:34 +05303623 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003624 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303625 adev->is_channel_status_set = true;
3626 }
3627
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003628 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003629 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003630 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003631 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003632 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3633 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303634 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3635 ALOGD("copl(%p):send next track params in gapless", out);
3636 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3637 out->send_next_track_params = false;
3638 out->is_compr_metadata_avail = false;
3639 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003640 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303641 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303642 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003643
Ashish Jain83a6cc22016-06-28 14:34:17 +05303644 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303645 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303646 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303647 pthread_mutex_unlock(&out->lock);
3648 return -EINVAL;
3649 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303650 audio_format_t dst_format = out->hal_op_format;
3651 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303652
3653 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3654 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3655
Ashish Jain83a6cc22016-06-28 14:34:17 +05303656 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303657 dst_format,
3658 buffer,
3659 src_format,
3660 frames);
3661
Ashish Jain83a6cc22016-06-28 14:34:17 +05303662 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303663 bytes_to_write);
3664
3665 /*Convert written bytes in audio flinger format*/
3666 if (ret > 0)
3667 ret = ((ret * format_to_bitwidth_table[out->format]) /
3668 format_to_bitwidth_table[dst_format]);
3669 }
3670 } else
3671 ret = compress_write(out->compr, buffer, bytes);
3672
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303673 if (ret < 0)
3674 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303675 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303676 /*msg to cb thread only if non blocking write is enabled*/
3677 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303678 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003679 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303680 } else if (-ENETRESET == ret) {
3681 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303682 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05303683 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05303684 out_on_error(&out->stream.common);
Naresh Tanniru80659832014-06-04 18:17:56 +05303685 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003686 }
Ashish Jain5106d362016-05-11 19:23:33 +05303687 if ( ret == (ssize_t)bytes && !out->non_blocking)
3688 out->written += bytes;
3689
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303690 /* Call compr start only when non-zero bytes of data is there to be rendered */
3691 if (!out->playback_started && ret > 0) {
3692 int status = compress_start(out->compr);
3693 if (status < 0) {
3694 ret = status;
3695 ALOGE("%s: compr start failed with err %d", __func__, errno);
3696 goto exit;
3697 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003698 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003699 out->playback_started = 1;
3700 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003701
3702 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3703 popcount(out->channel_mask),
3704 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003705 }
3706 pthread_mutex_unlock(&out->lock);
3707 return ret;
3708 } else {
3709 if (out->pcm) {
3710 if (out->muted)
3711 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003712
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303713 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003714
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003715 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003716
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003717 if (out->config.rate)
3718 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3719 out->config.rate;
3720
3721 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3722
3723 request_out_focus(out, ns);
3724
3725 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003726 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003727 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303728 out->convert_buffer != NULL) {
3729
3730 memcpy_by_audio_format(out->convert_buffer,
3731 out->hal_op_format,
3732 buffer,
3733 out->hal_ip_format,
3734 out->config.period_size * out->config.channels);
3735
3736 ret = pcm_write(out->pcm, out->convert_buffer,
3737 (out->config.period_size *
3738 out->config.channels *
3739 format_to_bitwidth_table[out->hal_op_format]));
3740 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05303741 /*
3742 * To avoid underrun in DSP when the application is not pumping
3743 * data at required rate, check for the no. of bytes and ignore
3744 * pcm_write if it is less than actual buffer size.
3745 * It is a work around to a change in compress VOIP driver.
3746 */
3747 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
3748 bytes < (out->config.period_size * out->config.channels *
3749 audio_bytes_per_sample(out->format))) {
3750 size_t voip_buf_size =
3751 out->config.period_size * out->config.channels *
3752 audio_bytes_per_sample(out->format);
3753 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
3754 __func__, bytes, voip_buf_size);
3755 usleep(((uint64_t)voip_buf_size - bytes) *
3756 1000000 / audio_stream_out_frame_size(stream) /
3757 out_get_sample_rate(&out->stream.common));
3758 ret = 0;
3759 } else
3760 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303761 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003762
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003763 release_out_focus(out);
3764
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303765 if (ret < 0)
3766 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303767 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3768 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3769 else
3770 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003771 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772 }
3773
3774exit:
Naresh Tanniru4c630392014-05-12 01:05:52 +05303775 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303776 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303777 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778 pthread_mutex_unlock(&out->lock);
3779
3780 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003781 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003782 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303783 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303784 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303785 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303786 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303787 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303788 out->standby = true;
3789 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303790 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303791 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3792 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3793 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003794 }
3795 return bytes;
3796}
3797
3798static int out_get_render_position(const struct audio_stream_out *stream,
3799 uint32_t *dsp_frames)
3800{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003801 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08003802
3803 if (dsp_frames == NULL)
3804 return -EINVAL;
3805
3806 *dsp_frames = 0;
3807 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003808 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303809
3810 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3811 * this operation and adev_close_output_stream(where out gets reset).
3812 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303813 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303814 *dsp_frames = get_actual_pcm_frames_rendered(out);
3815 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3816 return 0;
3817 }
3818
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003819 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303820 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303821 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003822 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303823 if (ret < 0)
3824 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003825 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303826 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003827 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303828 if (-ENETRESET == ret) {
3829 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303830 out->card_status = CARD_STATUS_OFFLINE;
3831 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303832 } else if(ret < 0) {
3833 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303834 ret = -EINVAL;
3835 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303836 /*
3837 * Handle corner case where compress session is closed during SSR
3838 * and timestamp is queried
3839 */
3840 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303841 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303842 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303843 ret = 0;
Naresh Tanniru80659832014-06-04 18:17:56 +05303844 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303845 pthread_mutex_unlock(&out->lock);
3846 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08003847 } else if (audio_is_linear_pcm(out->format)) {
3848 *dsp_frames = out->written;
3849 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003850 } else
3851 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003852}
3853
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003854static int out_add_audio_effect(const struct audio_stream *stream __unused,
3855 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003856{
3857 return 0;
3858}
3859
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003860static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3861 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003862{
3863 return 0;
3864}
3865
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003866static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3867 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003868{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303869 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870}
3871
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003872static int out_get_presentation_position(const struct audio_stream_out *stream,
3873 uint64_t *frames, struct timespec *timestamp)
3874{
3875 struct stream_out *out = (struct stream_out *)stream;
3876 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003877 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003878
Ashish Jain5106d362016-05-11 19:23:33 +05303879 /* below piece of code is not guarded against any lock because audioFliner serializes
3880 * this operation and adev_close_output_stream( where out gets reset).
3881 */
3882 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303883 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303884 *frames = get_actual_pcm_frames_rendered(out);
3885 /* this is the best we can do */
3886 clock_gettime(CLOCK_MONOTONIC, timestamp);
3887 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3888 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3889 return 0;
3890 }
3891
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003892 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003893
Ashish Jain5106d362016-05-11 19:23:33 +05303894 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3895 ret = compress_get_tstamp(out->compr, &dsp_frames,
3896 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08003897 // Adjustment accounts for A2dp encoder latency with offload usecases
3898 // Note: Encoder latency is returned in ms.
3899 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3900 unsigned long offset =
3901 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3902 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3903 }
Ashish Jain5106d362016-05-11 19:23:33 +05303904 ALOGVV("%s rendered frames %ld sample_rate %d",
3905 __func__, dsp_frames, out->sample_rate);
3906 *frames = dsp_frames;
3907 if (ret < 0)
3908 ret = -errno;
3909 if (-ENETRESET == ret) {
3910 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303911 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05303912 ret = -EINVAL;
3913 } else
3914 ret = 0;
3915 /* this is the best we can do */
3916 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003917 } else {
3918 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003919 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003920 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3921 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003922 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003923 // This adjustment accounts for buffering after app processor.
3924 // It is based on estimated DSP latency per use case, rather than exact.
3925 signed_frames -=
3926 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3927
Aniket Kumar Lataff613152017-07-18 18:19:21 -07003928 // Adjustment accounts for A2dp encoder latency with non offload usecases
3929 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3930 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3931 signed_frames -=
3932 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3933 }
3934
Eric Laurent949a0892013-09-20 09:20:13 -07003935 // It would be unusual for this value to be negative, but check just in case ...
3936 if (signed_frames >= 0) {
3937 *frames = signed_frames;
3938 ret = 0;
3939 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003940 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303941 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303942 *frames = out->written;
3943 clock_gettime(CLOCK_MONOTONIC, timestamp);
3944 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003945 }
3946 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003947 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003948 return ret;
3949}
3950
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003951static int out_set_callback(struct audio_stream_out *stream,
3952 stream_callback_t callback, void *cookie)
3953{
3954 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003955 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003956
3957 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003958 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003959 out->client_callback = callback;
3960 out->client_cookie = cookie;
3961 if (out->adsp_hdlr_stream_handle) {
3962 ret = audio_extn_adsp_hdlr_stream_set_callback(
3963 out->adsp_hdlr_stream_handle,
3964 callback,
3965 cookie);
3966 if (ret)
3967 ALOGW("%s:adsp hdlr callback registration failed %d",
3968 __func__, ret);
3969 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003970 pthread_mutex_unlock(&out->lock);
3971 return 0;
3972}
3973
3974static int out_pause(struct audio_stream_out* stream)
3975{
3976 struct stream_out *out = (struct stream_out *)stream;
3977 int status = -ENOSYS;
3978 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003979 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003980 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003981 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003982 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303983 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05303984 status = compress_pause(out->compr);
3985
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003986 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003987
Mingming Yin21854652016-04-13 11:54:02 -07003988 if (audio_extn_passthru_is_active()) {
3989 ALOGV("offload use case, pause passthru");
3990 audio_extn_passthru_on_pause(out);
3991 }
3992
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303993 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003994 audio_extn_dts_notify_playback_state(out->usecase, 0,
3995 out->sample_rate, popcount(out->channel_mask),
3996 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003997 }
3998 pthread_mutex_unlock(&out->lock);
3999 }
4000 return status;
4001}
4002
4003static int out_resume(struct audio_stream_out* stream)
4004{
4005 struct stream_out *out = (struct stream_out *)stream;
4006 int status = -ENOSYS;
4007 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004008 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004009 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004010 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004011 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004012 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304013 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304014 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004015 }
4016 if (!status) {
4017 out->offload_state = OFFLOAD_STATE_PLAYING;
4018 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304019 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004020 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4021 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004022 }
4023 pthread_mutex_unlock(&out->lock);
4024 }
4025 return status;
4026}
4027
4028static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
4029{
4030 struct stream_out *out = (struct stream_out *)stream;
4031 int status = -ENOSYS;
4032 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004033 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004034 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004035 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
4036 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
4037 else
4038 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
4039 pthread_mutex_unlock(&out->lock);
4040 }
4041 return status;
4042}
4043
4044static int out_flush(struct audio_stream_out* stream)
4045{
4046 struct stream_out *out = (struct stream_out *)stream;
4047 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004048 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004049 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004050 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004051 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
4052 stop_compressed_output_l(out);
4053 out->written = 0;
4054 } else {
4055 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
4056 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004057 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004058 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004059 return 0;
4060 }
4061 return -ENOSYS;
4062}
4063
Haynes Mathew George16081042017-05-31 17:16:49 -07004064static int out_stop(const struct audio_stream_out* stream)
4065{
4066 struct stream_out *out = (struct stream_out *)stream;
4067 struct audio_device *adev = out->dev;
4068 int ret = -ENOSYS;
4069
4070 ALOGV("%s", __func__);
4071 pthread_mutex_lock(&adev->lock);
4072 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4073 out->playback_started && out->pcm != NULL) {
4074 pcm_stop(out->pcm);
4075 ret = stop_output_stream(out);
4076 out->playback_started = false;
4077 }
4078 pthread_mutex_unlock(&adev->lock);
4079 return ret;
4080}
4081
4082static int out_start(const struct audio_stream_out* stream)
4083{
4084 struct stream_out *out = (struct stream_out *)stream;
4085 struct audio_device *adev = out->dev;
4086 int ret = -ENOSYS;
4087
4088 ALOGV("%s", __func__);
4089 pthread_mutex_lock(&adev->lock);
4090 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4091 !out->playback_started && out->pcm != NULL) {
4092 ret = start_output_stream(out);
4093 if (ret == 0) {
4094 out->playback_started = true;
4095 }
4096 }
4097 pthread_mutex_unlock(&adev->lock);
4098 return ret;
4099}
4100
4101/*
4102 * Modify config->period_count based on min_size_frames
4103 */
4104static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
4105{
4106 int periodCountRequested = (min_size_frames + config->period_size - 1)
4107 / config->period_size;
4108 int periodCount = MMAP_PERIOD_COUNT_MIN;
4109
4110 ALOGV("%s original config.period_size = %d config.period_count = %d",
4111 __func__, config->period_size, config->period_count);
4112
4113 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
4114 periodCount *= 2;
4115 }
4116 config->period_count = periodCount;
4117
4118 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
4119}
4120
4121static int out_create_mmap_buffer(const struct audio_stream_out *stream,
4122 int32_t min_size_frames,
4123 struct audio_mmap_buffer_info *info)
4124{
4125 struct stream_out *out = (struct stream_out *)stream;
4126 struct audio_device *adev = out->dev;
4127 int ret = 0;
4128 unsigned int offset1;
4129 unsigned int frames1;
4130 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004131 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07004132
4133 ALOGV("%s", __func__);
4134 pthread_mutex_lock(&adev->lock);
4135
4136 if (info == NULL || min_size_frames == 0) {
4137 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
4138 ret = -EINVAL;
4139 goto exit;
4140 }
4141 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
4142 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
4143 ret = -ENOSYS;
4144 goto exit;
4145 }
4146 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4147 if (out->pcm_device_id < 0) {
4148 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4149 __func__, out->pcm_device_id, out->usecase);
4150 ret = -EINVAL;
4151 goto exit;
4152 }
4153
4154 adjust_mmap_period_count(&out->config, min_size_frames);
4155
4156 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4157 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
4158 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
4159 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
4160 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4161 step = "open";
4162 ret = -ENODEV;
4163 goto exit;
4164 }
4165 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
4166 if (ret < 0) {
4167 step = "begin";
4168 goto exit;
4169 }
4170 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
4171 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004172 ret = platform_get_mmap_data_fd(adev->platform,
4173 out->pcm_device_id, 0 /*playback*/,
4174 &info->shared_memory_fd,
4175 &mmap_size);
4176 if (ret < 0) {
4177 step = "get_mmap_fd";
4178 goto exit;
4179 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004180 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004181 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07004182
4183 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
4184 if (ret < 0) {
4185 step = "commit";
4186 goto exit;
4187 }
4188
4189 out->standby = false;
4190 ret = 0;
4191
4192 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4193 __func__, info->shared_memory_address, info->buffer_size_frames);
4194
4195exit:
4196 if (ret != 0) {
4197 if (out->pcm == NULL) {
4198 ALOGE("%s: %s - %d", __func__, step, ret);
4199 } else {
4200 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
4201 pcm_close(out->pcm);
4202 out->pcm = NULL;
4203 }
4204 }
4205 pthread_mutex_unlock(&adev->lock);
4206 return ret;
4207}
4208
4209static int out_get_mmap_position(const struct audio_stream_out *stream,
4210 struct audio_mmap_position *position)
4211{
4212 struct stream_out *out = (struct stream_out *)stream;
4213 ALOGVV("%s", __func__);
4214 if (position == NULL) {
4215 return -EINVAL;
4216 }
4217 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
4218 return -ENOSYS;
4219 }
4220 if (out->pcm == NULL) {
4221 return -ENOSYS;
4222 }
4223
4224 struct timespec ts = { 0, 0 };
4225 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
4226 if (ret < 0) {
4227 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
4228 return ret;
4229 }
4230 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4231 return 0;
4232}
4233
4234
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004235/** audio_stream_in implementation **/
4236static uint32_t in_get_sample_rate(const struct audio_stream *stream)
4237{
4238 struct stream_in *in = (struct stream_in *)stream;
4239
4240 return in->config.rate;
4241}
4242
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004243static int in_set_sample_rate(struct audio_stream *stream __unused,
4244 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245{
4246 return -ENOSYS;
4247}
4248
4249static size_t in_get_buffer_size(const struct audio_stream *stream)
4250{
4251 struct stream_in *in = (struct stream_in *)stream;
4252
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004253 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
4254 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004255 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
4256 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 -07004257 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
4258 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304259 else if(audio_extn_cin_attached_usecase(in->usecase))
4260 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004261
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004262 return in->config.period_size * in->af_period_multiplier *
4263 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004264}
4265
4266static uint32_t in_get_channels(const struct audio_stream *stream)
4267{
4268 struct stream_in *in = (struct stream_in *)stream;
4269
4270 return in->channel_mask;
4271}
4272
4273static audio_format_t in_get_format(const struct audio_stream *stream)
4274{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004275 struct stream_in *in = (struct stream_in *)stream;
4276
4277 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004278}
4279
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004280static int in_set_format(struct audio_stream *stream __unused,
4281 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004282{
4283 return -ENOSYS;
4284}
4285
4286static int in_standby(struct audio_stream *stream)
4287{
4288 struct stream_in *in = (struct stream_in *)stream;
4289 struct audio_device *adev = in->dev;
4290 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304291 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4292 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07004293 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304294
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004295 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004296 if (!in->standby && in->is_st_session) {
4297 ALOGD("%s: sound trigger pcm stop lab", __func__);
4298 audio_extn_sound_trigger_stop_lab(in);
4299 in->standby = 1;
4300 }
4301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004303 if (adev->adm_deregister_stream)
4304 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
4305
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004306 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004307 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004308 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
4309 voice_extn_compress_voip_close_input_stream(stream);
4310 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07004311 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4312 do_stop = in->capture_started;
4313 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08004314 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304315 if (audio_extn_cin_attached_usecase(in->usecase))
4316 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08004317 if (in->pcm) {
4318 pcm_close(in->pcm);
4319 in->pcm = NULL;
4320 }
4321 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004322 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004323 if (in->pcm) {
4324 pcm_close(in->pcm);
4325 in->pcm = NULL;
4326 }
4327
4328 if (do_stop) {
4329 status = stop_input_stream(in);
4330 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004331 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004332 }
4333 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07004334 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004335 return status;
4336}
4337
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004338static int in_dump(const struct audio_stream *stream __unused,
4339 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004340{
4341 return 0;
4342}
4343
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304344static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4345{
4346 if (!stream || !parms)
4347 return;
4348
4349 struct stream_in *in = (struct stream_in *)stream;
4350 struct audio_device *adev = in->dev;
4351
4352 card_status_t status;
4353 int card;
4354 if (parse_snd_card_status(parms, &card, &status) < 0)
4355 return;
4356
4357 pthread_mutex_lock(&adev->lock);
4358 bool valid_cb = (card == adev->snd_card);
4359 pthread_mutex_unlock(&adev->lock);
4360
4361 if (!valid_cb)
4362 return;
4363
4364 lock_input_stream(in);
4365 if (in->card_status != status)
4366 in->card_status = status;
4367 pthread_mutex_unlock(&in->lock);
4368
4369 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4370 use_case_table[in->usecase],
4371 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4372
4373 // a better solution would be to report error back to AF and let
4374 // it put the stream to standby
4375 if (status == CARD_STATUS_OFFLINE)
4376 in_standby(&in->stream.common);
4377
4378 return;
4379}
4380
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4382{
4383 struct stream_in *in = (struct stream_in *)stream;
4384 struct audio_device *adev = in->dev;
4385 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004386 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004387 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004388
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304389 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390 parms = str_parms_create_str(kvpairs);
4391
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304392 if (!parms)
4393 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004394 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004395 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004396
4397 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4398 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004399 val = atoi(value);
4400 /* no audio source uses val == 0 */
4401 if ((in->source != val) && (val != 0)) {
4402 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004403 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4404 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4405 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004406 (in->config.rate == 8000 || in->config.rate == 16000 ||
4407 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004408 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004409 err = voice_extn_compress_voip_open_input_stream(in);
4410 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004411 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004412 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004413 }
4414 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004415 }
4416 }
4417
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004418 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4419 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004421 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004422 in->device = val;
4423 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004424 if (!in->standby && !in->is_st_session) {
4425 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07004426 if (adev->adm_on_routing_change)
4427 adev->adm_on_routing_change(adev->adm_data,
4428 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004429 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004430 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004431 }
4432 }
4433
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304434 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4435 if (err >= 0) {
4436 strlcpy(in->profile, value, sizeof(in->profile));
4437 ALOGV("updating stream profile with value '%s'", in->profile);
4438 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4439 &adev->streams_input_cfg_list,
4440 in->device, in->flags, in->format,
4441 in->sample_rate, in->bit_width,
4442 in->profile, &in->app_type_cfg);
4443 }
4444
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004445 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004446 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004447
4448 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304449error:
Eric Laurent994a6932013-07-17 11:51:42 -07004450 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004451 return ret;
4452}
4453
4454static char* in_get_parameters(const struct audio_stream *stream,
4455 const char *keys)
4456{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004457 struct stream_in *in = (struct stream_in *)stream;
4458 struct str_parms *query = str_parms_create_str(keys);
4459 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004460 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004461
4462 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004463 if (reply) {
4464 str_parms_destroy(reply);
4465 }
4466 if (query) {
4467 str_parms_destroy(query);
4468 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004469 ALOGE("in_get_parameters: failed to create query or reply");
4470 return NULL;
4471 }
4472
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004473 ALOGV("%s: enter: keys - %s", __func__, keys);
4474
4475 voice_extn_in_get_parameters(in, query, reply);
4476
4477 str = str_parms_to_str(reply);
4478 str_parms_destroy(query);
4479 str_parms_destroy(reply);
4480
4481 ALOGV("%s: exit: returns - %s", __func__, str);
4482 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004483}
4484
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004485static int in_set_gain(struct audio_stream_in *stream __unused,
4486 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004487{
4488 return 0;
4489}
4490
4491static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4492 size_t bytes)
4493{
4494 struct stream_in *in = (struct stream_in *)stream;
4495 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304496 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304497 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004498
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004499 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304500
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004501 if (in->is_st_session) {
4502 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
4503 /* Read from sound trigger HAL */
4504 audio_extn_sound_trigger_read(in, buffer, bytes);
4505 pthread_mutex_unlock(&in->lock);
4506 return bytes;
4507 }
4508
Haynes Mathew George16081042017-05-31 17:16:49 -07004509 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4510 ret = -ENOSYS;
4511 goto exit;
4512 }
4513
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004514 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004515 pthread_mutex_lock(&adev->lock);
4516 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
4517 ret = voice_extn_compress_voip_start_input_stream(in);
4518 else
4519 ret = start_input_stream(in);
4520 pthread_mutex_unlock(&adev->lock);
4521 if (ret != 0) {
4522 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004523 }
4524 in->standby = 0;
4525 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004526
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004527 // what's the duration requested by the client?
4528 long ns = 0;
4529
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304530 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004531 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4532 in->config.rate;
4533
4534 request_in_focus(in, ns);
4535 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004536
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304537 if (audio_extn_cin_attached_usecase(in->usecase)) {
4538 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
4539 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304540 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004541 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304542 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07004543 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004544 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004545 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304546 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004547 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304548 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4549 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4550 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
4551 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304552 ret = -EINVAL;
4553 goto exit;
4554 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304555 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304556 ret = -errno;
4557 }
4558 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304559 /* bytes read is always set to bytes for non compress usecases */
4560 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004561 }
4562
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004563 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004565 /*
4566 * Instead of writing zeroes here, we could trust the hardware
4567 * to always provide zeroes when muted.
4568 */
Pavan Chikkala63964842014-12-04 10:48:28 +05304569 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
4570 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004571 memset(buffer, 0, bytes);
4572
4573exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004574 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304575 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004576 pthread_mutex_unlock(&in->lock);
4577
4578 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304579 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304580 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304581 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304582 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304583 in->standby = true;
4584 }
Sharad Sangled17c9122017-03-20 15:58:52 +05304585 if (!audio_extn_cin_attached_usecase(in->usecase)) {
4586 bytes_read = bytes;
4587 memset(buffer, 0, bytes);
4588 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004589 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004590 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05304591 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05304592 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004593 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304594 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004595}
4596
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004597static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004598{
4599 return 0;
4600}
4601
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004602static int add_remove_audio_effect(const struct audio_stream *stream,
4603 effect_handle_t effect,
4604 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004605{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004606 struct stream_in *in = (struct stream_in *)stream;
4607 int status = 0;
4608 effect_descriptor_t desc;
4609
4610 status = (*effect)->get_descriptor(effect, &desc);
4611 if (status != 0)
4612 return status;
4613
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004614 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004615 pthread_mutex_lock(&in->dev->lock);
4616 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4617 in->enable_aec != enable &&
4618 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4619 in->enable_aec = enable;
4620 if (!in->standby)
4621 select_devices(in->dev, in->usecase);
4622 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08004623 if (in->enable_ns != enable &&
4624 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4625 in->enable_ns = enable;
4626 if (!in->standby)
4627 select_devices(in->dev, in->usecase);
4628 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004629 pthread_mutex_unlock(&in->dev->lock);
4630 pthread_mutex_unlock(&in->lock);
4631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004632 return 0;
4633}
4634
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004635static int in_add_audio_effect(const struct audio_stream *stream,
4636 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004637{
Eric Laurent994a6932013-07-17 11:51:42 -07004638 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004639 return add_remove_audio_effect(stream, effect, true);
4640}
4641
4642static int in_remove_audio_effect(const struct audio_stream *stream,
4643 effect_handle_t effect)
4644{
Eric Laurent994a6932013-07-17 11:51:42 -07004645 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004646 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647}
4648
Haynes Mathew George16081042017-05-31 17:16:49 -07004649static int in_stop(const struct audio_stream_in* stream)
4650{
4651 struct stream_in *in = (struct stream_in *)stream;
4652 struct audio_device *adev = in->dev;
4653
4654 int ret = -ENOSYS;
4655 ALOGV("%s", __func__);
4656 pthread_mutex_lock(&adev->lock);
4657 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4658 in->capture_started && in->pcm != NULL) {
4659 pcm_stop(in->pcm);
4660 ret = stop_input_stream(in);
4661 in->capture_started = false;
4662 }
4663 pthread_mutex_unlock(&adev->lock);
4664 return ret;
4665}
4666
4667static int in_start(const struct audio_stream_in* stream)
4668{
4669 struct stream_in *in = (struct stream_in *)stream;
4670 struct audio_device *adev = in->dev;
4671 int ret = -ENOSYS;
4672
4673 ALOGV("%s in %p", __func__, in);
4674 pthread_mutex_lock(&adev->lock);
4675 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4676 !in->capture_started && in->pcm != NULL) {
4677 if (!in->capture_started) {
4678 ret = start_input_stream(in);
4679 if (ret == 0) {
4680 in->capture_started = true;
4681 }
4682 }
4683 }
4684 pthread_mutex_unlock(&adev->lock);
4685 return ret;
4686}
4687
4688static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4689 int32_t min_size_frames,
4690 struct audio_mmap_buffer_info *info)
4691{
4692 struct stream_in *in = (struct stream_in *)stream;
4693 struct audio_device *adev = in->dev;
4694 int ret = 0;
4695 unsigned int offset1;
4696 unsigned int frames1;
4697 const char *step = "";
4698
4699 pthread_mutex_lock(&adev->lock);
4700 ALOGV("%s in %p", __func__, in);
4701
4702 if (info == NULL || min_size_frames == 0) {
4703 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
4704 ret = -EINVAL;
4705 goto exit;
4706 }
4707 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
4708 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
4709 ALOGV("%s in %p", __func__, in);
4710 ret = -ENOSYS;
4711 goto exit;
4712 }
4713 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4714 if (in->pcm_device_id < 0) {
4715 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4716 __func__, in->pcm_device_id, in->usecase);
4717 ret = -EINVAL;
4718 goto exit;
4719 }
4720
4721 adjust_mmap_period_count(&in->config, min_size_frames);
4722
4723 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4724 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4725 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4726 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4727 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4728 step = "open";
4729 ret = -ENODEV;
4730 goto exit;
4731 }
4732
4733 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4734 if (ret < 0) {
4735 step = "begin";
4736 goto exit;
4737 }
4738 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
4739 info->burst_size_frames = in->config.period_size;
4740 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4741
4742 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
4743 info->buffer_size_frames));
4744
4745 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4746 if (ret < 0) {
4747 step = "commit";
4748 goto exit;
4749 }
4750
4751 in->standby = false;
4752 ret = 0;
4753
4754 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4755 __func__, info->shared_memory_address, info->buffer_size_frames);
4756
4757exit:
4758 if (ret != 0) {
4759 if (in->pcm == NULL) {
4760 ALOGE("%s: %s - %d", __func__, step, ret);
4761 } else {
4762 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
4763 pcm_close(in->pcm);
4764 in->pcm = NULL;
4765 }
4766 }
4767 pthread_mutex_unlock(&adev->lock);
4768 return ret;
4769}
4770
4771static int in_get_mmap_position(const struct audio_stream_in *stream,
4772 struct audio_mmap_position *position)
4773{
4774 struct stream_in *in = (struct stream_in *)stream;
4775 ALOGVV("%s", __func__);
4776 if (position == NULL) {
4777 return -EINVAL;
4778 }
4779 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
4780 return -ENOSYS;
4781 }
4782 if (in->pcm == NULL) {
4783 return -ENOSYS;
4784 }
4785 struct timespec ts = { 0, 0 };
4786 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
4787 if (ret < 0) {
4788 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
4789 return ret;
4790 }
4791 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4792 return 0;
4793}
4794
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304795int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07004796 audio_io_handle_t handle,
4797 audio_devices_t devices,
4798 audio_output_flags_t flags,
4799 struct audio_config *config,
4800 struct audio_stream_out **stream_out,
4801 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004802{
4803 struct audio_device *adev = (struct audio_device *)dev;
4804 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304805 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004806 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004807 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004809 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304810
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004811 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4812
Mingming Yin3a941d42016-02-17 18:08:05 -08004813 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
4814 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304815 devices, flags, &out->stream);
4816
4817
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004818 if (!out) {
4819 return -ENOMEM;
4820 }
4821
Haynes Mathew George204045b2015-02-25 20:32:03 -08004822 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004823 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304824 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08004825 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4826
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004827 if (devices == AUDIO_DEVICE_NONE)
4828 devices = AUDIO_DEVICE_OUT_SPEAKER;
4829
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004830 out->flags = flags;
4831 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004832 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004833 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004834 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05304835 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05304836 if (out->channel_mask == AUDIO_CHANNEL_NONE)
4837 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
4838 else
4839 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07004840 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004841 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08004842 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304843 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304844 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304845 out->a2dp_compress_mute = false;
Alexy Joseph98988832017-01-13 14:56:59 -08004846 out->dynamic_pm_qos_enabled = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004847
Mingming Yin3a941d42016-02-17 18:08:05 -08004848 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4849 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
4850 pthread_mutex_lock(&adev->lock);
4851 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
4852 ret = read_hdmi_sink_caps(out);
4853 pthread_mutex_unlock(&adev->lock);
4854 if (ret != 0) {
4855 if (ret == -ENOSYS) {
4856 /* ignore and go with default */
4857 ret = 0;
4858 } else {
4859 ALOGE("error reading hdmi sink caps");
4860 goto error_open;
4861 }
4862 }
4863 }
4864
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004865 /* Init use case and pcm_config */
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004866#ifndef COMPRESS_VOIP_ENABLED
4867 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4868 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
4869 out->sample_rate == 32000 || out->sample_rate == 48000)) {
4870 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
4871 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
4872 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4873
4874 out->config = default_pcm_config_voip_copp;
4875 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
4876 out->config.rate = out->sample_rate;
4877
4878#else
Dhananjay Kumarac341582017-02-23 23:42:25 +05304879 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004880 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08004881 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004882 ret = voice_extn_compress_voip_open_output_stream(out);
4883 if (ret != 0) {
4884 ALOGE("%s: Compress voip output cannot be opened, error:%d",
4885 __func__, ret);
4886 goto error_open;
4887 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004888#endif
vivek mehta0ea887a2015-08-26 14:01:20 -07004889 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304890 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304891 pthread_mutex_lock(&adev->lock);
4892 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4893 pthread_mutex_unlock(&adev->lock);
4894
4895 // reject offload during card offline to allow
4896 // fallback to s/w paths
4897 if (offline) {
4898 ret = -ENODEV;
4899 goto error_open;
4900 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004901
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004902 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4903 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4904 ALOGE("%s: Unsupported Offload information", __func__);
4905 ret = -EINVAL;
4906 goto error_open;
4907 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004908
Mingming Yin3a941d42016-02-17 18:08:05 -08004909 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004910 if(config->offload_info.format == 0)
4911 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004912 if (config->offload_info.sample_rate == 0)
4913 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004914 }
4915
Mingming Yin90310102013-11-13 16:57:00 -08004916 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304917 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004918 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004919 ret = -EINVAL;
4920 goto error_open;
4921 }
4922
Ben Romberger0f8c87b2017-05-24 17:41:11 -07004923 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
4924 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
4925 (audio_extn_passthru_is_passthrough_stream(out)) &&
4926 !((config->sample_rate == 48000) ||
4927 (config->sample_rate == 96000) ||
4928 (config->sample_rate == 192000))) {
4929 ALOGE("%s: Unsupported sample rate %d for audio format %x",
4930 __func__, config->sample_rate, config->offload_info.format);
4931 ret = -EINVAL;
4932 goto error_open;
4933 }
4934
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004935 out->compr_config.codec = (struct snd_codec *)
4936 calloc(1, sizeof(struct snd_codec));
4937
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004938 if (!out->compr_config.codec) {
4939 ret = -ENOMEM;
4940 goto error_open;
4941 }
4942
Dhananjay Kumarac341582017-02-23 23:42:25 +05304943 out->stream.pause = out_pause;
4944 out->stream.resume = out_resume;
4945 out->stream.flush = out_flush;
4946 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004947 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004948 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304949 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004950 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304951 } else {
4952 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4953 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004954 }
vivek mehta446c3962015-09-14 10:57:35 -07004955
4956 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004957 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4958 config->format == 0 && config->sample_rate == 0 &&
4959 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004960 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004961 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4962 } else {
4963 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4964 ret = -EEXIST;
4965 goto error_open;
4966 }
vivek mehta446c3962015-09-14 10:57:35 -07004967 }
4968
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004969 if (config->offload_info.channel_mask)
4970 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004971 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004972 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004973 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004974 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304975 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004976 ret = -EINVAL;
4977 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004978 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004979
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004980 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004981 out->sample_rate = config->offload_info.sample_rate;
4982
Mingming Yin3ee55c62014-08-04 14:23:35 -07004983 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004984
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304985 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4986 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4987 audio_extn_dolby_send_ddp_endp_params(adev);
4988 audio_extn_dolby_set_dmid(adev);
4989 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004990
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004991 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004992 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004993 out->compr_config.codec->bit_rate =
4994 config->offload_info.bit_rate;
4995 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304996 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004997 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304998 /* Update bit width only for non passthrough usecases.
4999 * For passthrough usecases, the output will always be opened @16 bit
5000 */
5001 if (!audio_extn_passthru_is_passthrough_stream(out))
5002 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305003
5004 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
5005 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
5006 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
5007
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005008 /*TODO: Do we need to change it for passthrough */
5009 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005010
Manish Dewangana6fc5442015-08-24 20:30:31 +05305011 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
5012 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305013 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05305014 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305015 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
5016 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305017
5018 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
5019 AUDIO_FORMAT_PCM) {
5020
5021 /*Based on platform support, configure appropriate alsa format for corresponding
5022 *hal input format.
5023 */
5024 out->compr_config.codec->format = hal_format_to_alsa(
5025 config->offload_info.format);
5026
Ashish Jain83a6cc22016-06-28 14:34:17 +05305027 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05305028 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305029 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305030
Dhananjay Kumarac341582017-02-23 23:42:25 +05305031 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05305032 *hal input format and alsa format might differ based on platform support.
5033 */
5034 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05305035 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305036
5037 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
5038
5039 /* Check if alsa session is configured with the same format as HAL input format,
5040 * if not then derive correct fragment size needed to accomodate the
5041 * conversion of HAL input format to alsa format.
5042 */
5043 audio_extn_utils_update_direct_pcm_fragment_size(out);
5044
5045 /*if hal input and output fragment size is different this indicates HAL input format is
5046 *not same as the alsa format
5047 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305048 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305049 /*Allocate a buffer to convert input data to the alsa configured format.
5050 *size of convert buffer is equal to the size required to hold one fragment size
5051 *worth of pcm data, this is because flinger does not write more than fragment_size
5052 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305053 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
5054 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05305055 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
5056 ret = -ENOMEM;
5057 goto error_open;
5058 }
5059 }
5060 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
5061 out->compr_config.fragment_size =
5062 audio_extn_passthru_get_buffer_size(&config->offload_info);
5063 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5064 } else {
5065 out->compr_config.fragment_size =
5066 platform_get_compress_offload_buffer_size(&config->offload_info);
5067 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5068 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07005069
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305070 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5071 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
5072 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07005073 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05305074 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005075
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05305076 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
5077 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
5078 }
5079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005080 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
5081 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005082
Manish Dewangan69426c82017-01-30 17:35:36 +05305083 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
5084 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
5085 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
5086 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5087 out->render_mode = RENDER_MODE_AUDIO_MASTER;
5088 } else {
5089 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
5090 }
Alexy Josephaa54c872014-12-03 02:46:47 -08005091
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05305092 memset(&out->channel_map_param, 0,
5093 sizeof(struct audio_out_channel_map_param));
5094
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005095 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305096 out->send_next_track_params = false;
5097 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005098 out->offload_state = OFFLOAD_STATE_IDLE;
5099 out->playback_started = 0;
5100
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005101 audio_extn_dts_create_state_notifier_node(out->usecase);
5102
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005103 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
5104 __func__, config->offload_info.version,
5105 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05305106
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305107 /* Check if DSD audio format is supported in codec
5108 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305109 */
5110
5111 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305112 (!platform_check_codec_dsd_support(adev->platform) ||
5113 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305114 ret = -EINVAL;
5115 goto error_open;
5116 }
5117
Ashish Jain5106d362016-05-11 19:23:33 +05305118 /* Disable gapless if any of the following is true
5119 * passthrough playback
5120 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05305121 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05305122 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305123 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305124 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07005125 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305126 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305127 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05305128 check_and_set_gapless_mode(adev, false);
5129 } else
5130 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07005131
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305132 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07005133 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5134 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305135 if (config->format == AUDIO_FORMAT_DSD) {
5136 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5137 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
5138 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07005139
5140 create_offload_callback_thread(out);
5141
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005142 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305143 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005144 if (ret != 0) {
5145 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
5146 __func__, ret);
5147 goto error_open;
5148 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005149 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
5150 if (config->sample_rate == 0)
5151 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5152 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5153 config->sample_rate != 8000) {
5154 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5155 ret = -EINVAL;
5156 goto error_open;
5157 }
5158 out->sample_rate = config->sample_rate;
5159 out->config.rate = config->sample_rate;
5160 if (config->format == AUDIO_FORMAT_DEFAULT)
5161 config->format = AUDIO_FORMAT_PCM_16_BIT;
5162 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5163 config->format = AUDIO_FORMAT_PCM_16_BIT;
5164 ret = -EINVAL;
5165 goto error_open;
5166 }
5167 out->format = config->format;
5168 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
5169 out->config = pcm_config_afe_proxy_playback;
5170 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005171 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05305172 unsigned int channels = 0;
5173 /*Update config params to default if not set by the caller*/
5174 if (config->sample_rate == 0)
5175 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5176 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5177 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5178 if (config->format == AUDIO_FORMAT_DEFAULT)
5179 config->format = AUDIO_FORMAT_PCM_16_BIT;
5180
5181 channels = audio_channel_count_from_out_mask(out->channel_mask);
5182
Ashish Jain83a6cc22016-06-28 14:34:17 +05305183 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
5184 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005185 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
5186 out->flags);
5187 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07005188 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
5189 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5190 out->config = pcm_config_mmap_playback;
5191 out->stream.start = out_start;
5192 out->stream.stop = out_stop;
5193 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5194 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305195 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
5196 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Alexy Joseph98988832017-01-13 14:56:59 -08005197 out->dynamic_pm_qos_enabled = property_get_bool("vendor.audio.dynamic.qos.enable", false);
5198 if (!out->dynamic_pm_qos_enabled) {
5199 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
5200 } else {
5201 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
5202 //the mixer path will be a string similar to "low-latency-playback resume"
5203 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
5204 strlcat(out->pm_qos_mixer_path,
5205 " resume", MAX_MIXER_PATH_LEN);
5206 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
5207 out->pm_qos_mixer_path);
5208 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305209 out->config = pcm_config_low_latency;
5210 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
5211 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5212 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05305213 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
5214 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
5215 if (out->config.period_size <= 0) {
5216 ALOGE("Invalid configuration period size is not valid");
5217 ret = -EINVAL;
5218 goto error_open;
5219 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305220 } else {
5221 /* primary path is the default path selected if no other outputs are available/suitable */
5222 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
5223 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
5224 }
5225 out->hal_ip_format = format = out->format;
5226 out->config.format = hal_format_to_pcm(out->hal_ip_format);
5227 out->hal_op_format = pcm_format_to_hal(out->config.format);
5228 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
5229 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005230 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05305231 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305232 if (out->hal_ip_format != out->hal_op_format) {
5233 uint32_t buffer_size = out->config.period_size *
5234 format_to_bitwidth_table[out->hal_op_format] *
5235 out->config.channels;
5236 out->convert_buffer = calloc(1, buffer_size);
5237 if (out->convert_buffer == NULL){
5238 ALOGE("Allocation failed for convert buffer for size %d",
5239 out->compr_config.fragment_size);
5240 ret = -ENOMEM;
5241 goto error_open;
5242 }
5243 ALOGD("Convert buffer allocated of size %d", buffer_size);
5244 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005245 }
5246
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005247 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
5248 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305249
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005250 /* TODO remove this hardcoding and check why width is zero*/
5251 if (out->bit_width == 0)
5252 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305253 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005254 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05305255 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305256 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05305257 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08005258 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
5259 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
5260 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005261 if(adev->primary_output == NULL)
5262 adev->primary_output = out;
5263 else {
5264 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005265 ret = -EEXIST;
5266 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005267 }
5268 }
5269
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005270 /* Check if this usecase is already existing */
5271 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07005272 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
5273 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005274 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005275 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005276 ret = -EEXIST;
5277 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005278 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005279
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005280 pthread_mutex_unlock(&adev->lock);
5281
5282 out->stream.common.get_sample_rate = out_get_sample_rate;
5283 out->stream.common.set_sample_rate = out_set_sample_rate;
5284 out->stream.common.get_buffer_size = out_get_buffer_size;
5285 out->stream.common.get_channels = out_get_channels;
5286 out->stream.common.get_format = out_get_format;
5287 out->stream.common.set_format = out_set_format;
5288 out->stream.common.standby = out_standby;
5289 out->stream.common.dump = out_dump;
5290 out->stream.common.set_parameters = out_set_parameters;
5291 out->stream.common.get_parameters = out_get_parameters;
5292 out->stream.common.add_audio_effect = out_add_audio_effect;
5293 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5294 out->stream.get_latency = out_get_latency;
5295 out->stream.set_volume = out_set_volume;
5296 out->stream.write = out_write;
5297 out->stream.get_render_position = out_get_render_position;
5298 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005299 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005300
Haynes Mathew George16081042017-05-31 17:16:49 -07005301 if (out->realtime)
5302 out->af_period_multiplier = af_period_multiplier;
5303 else
5304 out->af_period_multiplier = 1;
5305
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005306 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005307 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005308 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005309
5310 config->format = out->stream.common.get_format(&out->stream.common);
5311 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5312 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5313
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305314 /*
5315 By locking output stream before registering, we allow the callback
5316 to update stream's state only after stream's initial state is set to
5317 adev state.
5318 */
5319 lock_output_stream(out);
5320 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5321 pthread_mutex_lock(&adev->lock);
5322 out->card_status = adev->card_status;
5323 pthread_mutex_unlock(&adev->lock);
5324 pthread_mutex_unlock(&out->lock);
5325
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005326 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305327 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07005328 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005329
5330 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
5331 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5332 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005333 /* setup a channel for client <--> adsp communication for stream events */
5334 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07005335 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
5336 (audio_extn_ip_hdlr_intf_supported(config->format))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005337 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
5338 out->usecase, PCM_PLAYBACK);
5339 hdlr_stream_cfg.flags = out->flags;
5340 hdlr_stream_cfg.type = PCM_PLAYBACK;
5341 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
5342 &hdlr_stream_cfg);
5343 if (ret) {
5344 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
5345 out->adsp_hdlr_stream_handle = NULL;
5346 }
5347 }
Naresh Tanniru85819452017-05-04 18:55:45 -07005348 if (audio_extn_ip_hdlr_intf_supported(config->format)) {
5349 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL);
5350 if (ret < 0) {
5351 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
5352 out->ip_hdlr_handle = NULL;
5353 }
5354 }
Eric Laurent994a6932013-07-17 11:51:42 -07005355 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005356 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005357
5358error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05305359 if (out->convert_buffer)
5360 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005361 free(out);
5362 *stream_out = NULL;
5363 ALOGD("%s: exit: ret %d", __func__, ret);
5364 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005365}
5366
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305367void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005368 struct audio_stream_out *stream)
5369{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005370 struct stream_out *out = (struct stream_out *)stream;
5371 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005372 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005373
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305374 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
5375
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305376 // must deregister from sndmonitor first to prevent races
5377 // between the callback and close_stream
5378 audio_extn_snd_mon_unregister_listener(out);
5379
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005380 /* close adsp hdrl session before standby */
5381 if (out->adsp_hdlr_stream_handle) {
5382 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
5383 if (ret)
5384 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
5385 out->adsp_hdlr_stream_handle = NULL;
5386 }
5387
Naresh Tanniru85819452017-05-04 18:55:45 -07005388 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
5389 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
5390 out->ip_hdlr_handle = NULL;
5391 }
5392
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005393 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305394 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005395 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305396 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305397 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005398 if(ret != 0)
5399 ALOGE("%s: Compress voip output cannot be closed, error:%d",
5400 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005401 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005402 out_standby(&stream->common);
5403
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005404 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005405 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005406 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005407 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005408 if (out->compr_config.codec != NULL)
5409 free(out->compr_config.codec);
5410 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005411
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305412 out->a2dp_compress_mute = false;
5413
Ashish Jain83a6cc22016-06-28 14:34:17 +05305414 if (out->convert_buffer != NULL) {
5415 free(out->convert_buffer);
5416 out->convert_buffer = NULL;
5417 }
5418
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005419 if (adev->voice_tx_output == out)
5420 adev->voice_tx_output = NULL;
5421
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05305422 if (adev->primary_output == out)
5423 adev->primary_output = NULL;
5424
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005425 pthread_cond_destroy(&out->cond);
5426 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005427 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005428 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005429}
5430
5431static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5432{
5433 struct audio_device *adev = (struct audio_device *)dev;
5434 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005435 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005436 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005437 int ret;
5438 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005439
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005440 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005441 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005442
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305443 if (!parms)
5444 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305445
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305446 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
5447 if (ret >= 0) {
5448 /* When set to false, HAL should disable EC and NS */
5449 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5450 adev->bt_sco_on = true;
5451 else
5452 adev->bt_sco_on = false;
5453 }
5454
Naresh Tanniru4c630392014-05-12 01:05:52 +05305455 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005456 status = voice_set_parameters(adev, parms);
5457 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005458 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005459
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005460 status = platform_set_parameters(adev->platform, parms);
5461 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005462 goto done;
5463
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005464 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5465 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07005466 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005467 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5468 adev->bluetooth_nrec = true;
5469 else
5470 adev->bluetooth_nrec = false;
5471 }
5472
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005473 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5474 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005475 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5476 adev->screen_off = false;
5477 else
5478 adev->screen_off = true;
5479 }
5480
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005481 ret = str_parms_get_int(parms, "rotation", &val);
5482 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005483 bool reverse_speakers = false;
5484 switch(val) {
5485 // FIXME: note that the code below assumes that the speakers are in the correct placement
5486 // relative to the user when the device is rotated 90deg from its default rotation. This
5487 // assumption is device-specific, not platform-specific like this code.
5488 case 270:
5489 reverse_speakers = true;
5490 break;
5491 case 0:
5492 case 90:
5493 case 180:
5494 break;
5495 default:
5496 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005497 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005498 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005499 if (status == 0) {
5500 if (adev->speaker_lr_swap != reverse_speakers) {
5501 adev->speaker_lr_swap = reverse_speakers;
5502 // only update the selected device if there is active pcm playback
5503 struct audio_usecase *usecase;
5504 struct listnode *node;
5505 list_for_each(node, &adev->usecase_list) {
5506 usecase = node_to_item(node, struct audio_usecase, list);
5507 if (usecase->type == PCM_PLAYBACK) {
5508 select_devices(adev, usecase->id);
5509 break;
5510 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005511 }
5512 }
5513 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005514 }
5515
Mingming Yin514a8bc2014-07-29 15:22:21 -07005516 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5517 if (ret >= 0) {
5518 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5519 adev->bt_wb_speech_enabled = true;
5520 else
5521 adev->bt_wb_speech_enabled = false;
5522 }
5523
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005524 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5525 if (ret >= 0) {
5526 val = atoi(value);
5527 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005528 ALOGV("cache new ext disp type and edid");
5529 ret = platform_get_ext_disp_type(adev->platform);
5530 if (ret < 0) {
5531 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08005532 status = ret;
5533 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005534 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005535 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005536 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005537 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07005538 /*
5539 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
5540 * Per AudioPolicyManager, USB device is higher priority than WFD.
5541 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
5542 * If WFD use case occupies AFE proxy, it may result unintended behavior while
5543 * starting voice call on USB
5544 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005545 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5546 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08005547 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5548 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005549 }
vivek mehta344576a2016-04-12 18:56:03 -07005550 ALOGV("detected USB connect .. disable proxy");
5551 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005552 }
5553 }
5554
5555 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5556 if (ret >= 0) {
5557 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07005558 /*
5559 * The HDMI / Displayport disconnect handling has been moved to
5560 * audio extension to ensure that its parameters are not
5561 * invalidated prior to updating sysfs of the disconnect event
5562 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
5563 */
5564 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005565 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005566 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5567 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05305568 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5569 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005570 }
vivek mehta344576a2016-04-12 18:56:03 -07005571 ALOGV("detected USB disconnect .. enable proxy");
5572 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005573 }
5574 }
5575
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305576 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
5577 if (ret >= 0) {
5578 struct audio_usecase *usecase;
5579 struct listnode *node;
5580 list_for_each(node, &adev->usecase_list) {
5581 usecase = node_to_item(node, struct audio_usecase, list);
5582 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07005583 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305584 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08005585
5586 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305587 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08005588 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305589 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305590 //force device switch to re configure encoder
5591 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305592 audio_extn_a2dp_set_handoff_mode(false);
5593 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305594 break;
5595 }
5596 }
5597 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005598
5599 //handle vr audio setparam
5600 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5601 value, sizeof(value));
5602 if (ret >= 0) {
5603 ALOGI("Setting vr mode to be %s", value);
5604 if (!strncmp(value, "true", 4)) {
5605 adev->vr_audio_mode_enabled = true;
5606 ALOGI("Setting vr mode to true");
5607 } else if (!strncmp(value, "false", 5)) {
5608 adev->vr_audio_mode_enabled = false;
5609 ALOGI("Setting vr mode to false");
5610 } else {
5611 ALOGI("wrong vr mode set");
5612 }
5613 }
5614
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305615 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005616done:
5617 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005618 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305619error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005620 ALOGV("%s: exit with code(%d)", __func__, status);
5621 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005622}
5623
5624static char* adev_get_parameters(const struct audio_hw_device *dev,
5625 const char *keys)
5626{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005627 struct audio_device *adev = (struct audio_device *)dev;
5628 struct str_parms *reply = str_parms_create();
5629 struct str_parms *query = str_parms_create_str(keys);
5630 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05305631 char value[256] = {0};
5632 int ret = 0;
5633
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005634 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005635 if (reply) {
5636 str_parms_destroy(reply);
5637 }
5638 if (query) {
5639 str_parms_destroy(query);
5640 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005641 ALOGE("adev_get_parameters: failed to create query or reply");
5642 return NULL;
5643 }
5644
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005645 //handle vr audio getparam
5646
5647 ret = str_parms_get_str(query,
5648 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5649 value, sizeof(value));
5650
5651 if (ret >= 0) {
5652 bool vr_audio_enabled = false;
5653 pthread_mutex_lock(&adev->lock);
5654 vr_audio_enabled = adev->vr_audio_mode_enabled;
5655 pthread_mutex_unlock(&adev->lock);
5656
5657 ALOGI("getting vr mode to %d", vr_audio_enabled);
5658
5659 if (vr_audio_enabled) {
5660 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5661 "true");
5662 goto exit;
5663 } else {
5664 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5665 "false");
5666 goto exit;
5667 }
5668 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005669
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005670 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005671 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08005672 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005673 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05305674 pthread_mutex_unlock(&adev->lock);
5675
Naresh Tannirud7205b62014-06-20 02:54:48 +05305676exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005677 str = str_parms_to_str(reply);
5678 str_parms_destroy(query);
5679 str_parms_destroy(reply);
5680
5681 ALOGV("%s: exit: returns - %s", __func__, str);
5682 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005683}
5684
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005685static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005686{
5687 return 0;
5688}
5689
5690static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5691{
Haynes Mathew George5191a852013-09-11 14:19:36 -07005692 int ret;
5693 struct audio_device *adev = (struct audio_device *)dev;
5694 pthread_mutex_lock(&adev->lock);
5695 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07005696 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005697 pthread_mutex_unlock(&adev->lock);
5698 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005699}
5700
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005701static int adev_set_master_volume(struct audio_hw_device *dev __unused,
5702 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005703{
5704 return -ENOSYS;
5705}
5706
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005707static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5708 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005709{
5710 return -ENOSYS;
5711}
5712
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005713static int adev_set_master_mute(struct audio_hw_device *dev __unused,
5714 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005715{
5716 return -ENOSYS;
5717}
5718
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005719static int adev_get_master_mute(struct audio_hw_device *dev __unused,
5720 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005721{
5722 return -ENOSYS;
5723}
5724
5725static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5726{
5727 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005728
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005729 pthread_mutex_lock(&adev->lock);
5730 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005731 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005732 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08005733 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005734 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07005735 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005736 adev->current_call_output = NULL;
5737 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005738 }
5739 pthread_mutex_unlock(&adev->lock);
5740 return 0;
5741}
5742
5743static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5744{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005745 int ret;
5746
5747 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08005748 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005749 ret = voice_set_mic_mute((struct audio_device *)dev, state);
5750 pthread_mutex_unlock(&adev->lock);
5751
5752 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005753}
5754
5755static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5756{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005757 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005758 return 0;
5759}
5760
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005761static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005762 const struct audio_config *config)
5763{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005764 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005765
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005766 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
5767 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005768}
5769
5770static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005771 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005772 audio_devices_t devices,
5773 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005774 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305775 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005776 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005777 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005778{
5779 struct audio_device *adev = (struct audio_device *)dev;
5780 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005781 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005782 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005783 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305784 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305785
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005786 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305787 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
5788 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005789 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305790 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005791
5792 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005793
5794 if (!in) {
5795 ALOGE("failed to allocate input stream");
5796 return -ENOMEM;
5797 }
5798
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305799 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305800 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
5801 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005802 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005803 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005804
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005805 in->stream.common.get_sample_rate = in_get_sample_rate;
5806 in->stream.common.set_sample_rate = in_set_sample_rate;
5807 in->stream.common.get_buffer_size = in_get_buffer_size;
5808 in->stream.common.get_channels = in_get_channels;
5809 in->stream.common.get_format = in_get_format;
5810 in->stream.common.set_format = in_set_format;
5811 in->stream.common.standby = in_standby;
5812 in->stream.common.dump = in_dump;
5813 in->stream.common.set_parameters = in_set_parameters;
5814 in->stream.common.get_parameters = in_get_parameters;
5815 in->stream.common.add_audio_effect = in_add_audio_effect;
5816 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5817 in->stream.set_gain = in_set_gain;
5818 in->stream.read = in_read;
5819 in->stream.get_input_frames_lost = in_get_input_frames_lost;
5820
5821 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005822 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005823 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005824 in->standby = 1;
5825 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005826 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005827 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005828
Dhananjay Kumar973fc362017-01-09 18:48:15 +05305829 in->usecase = USECASE_AUDIO_RECORD;
5830 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Haynes Mathew George16081042017-05-31 17:16:49 -07005831 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Dhananjay Kumar973fc362017-01-09 18:48:15 +05305832 is_low_latency = true;
5833#if LOW_LATENCY_CAPTURE_USE_CASE
5834 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
5835#endif
5836 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
5837 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005838 in->format = config->format;
Haynes Mathew George16081042017-05-31 17:16:49 -07005839 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5840 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
5841 in->realtime = 0;
5842 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5843 in->config = pcm_config_mmap_capture;
5844 in->stream.start = in_start;
5845 in->stream.stop = in_stop;
5846 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5847 in->stream.get_mmap_position = in_get_mmap_position;
5848 in->af_period_multiplier = 1;
5849 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
5850 } else if (in->realtime) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005851 in->config = pcm_config_audio_capture_rt;
5852 in->sample_rate = in->config.rate;
5853 in->af_period_multiplier = af_period_multiplier;
5854 } else {
5855 in->config = pcm_config_audio_capture;
5856 in->config.rate = config->sample_rate;
5857 in->sample_rate = config->sample_rate;
5858 in->af_period_multiplier = 1;
5859 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305860 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005861
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305862 /* restrict 24 bit capture for unprocessed source only
5863 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
5864 */
5865 if (config->format == AUDIO_FORMAT_DEFAULT) {
5866 config->format = AUDIO_FORMAT_PCM_16_BIT;
5867 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
5868 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
5869 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
5870 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5871 bool ret_error = false;
5872 in->bit_width = 24;
5873 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5874 from HAL is 24_packed and 8_24
5875 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5876 24_packed return error indicating supported format is 24_packed
5877 *> In case of any other source requesting 24 bit or float return error
5878 indicating format supported is 16 bit only.
5879
5880 on error flinger will retry with supported format passed
5881 */
5882 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
5883 (source != AUDIO_SOURCE_CAMCORDER)) {
5884 config->format = AUDIO_FORMAT_PCM_16_BIT;
5885 if (config->sample_rate > 48000)
5886 config->sample_rate = 48000;
5887 ret_error = true;
5888 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
5889 in->config.format = PCM_FORMAT_S24_3LE;
5890 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5891 in->config.format = PCM_FORMAT_S24_LE;
5892 } else {
5893 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
5894 ret_error = true;
5895 }
5896
5897 if (ret_error) {
5898 ret = -EINVAL;
5899 goto err_open;
5900 }
5901 }
5902
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305903 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305904 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
5905 (adev->mode != AUDIO_MODE_IN_CALL)) {
5906 ret = -EINVAL;
5907 goto err_open;
5908 }
5909
5910 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
5911 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005912 if (config->sample_rate == 0)
5913 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5914 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5915 config->sample_rate != 8000) {
5916 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5917 ret = -EINVAL;
5918 goto err_open;
5919 }
5920 if (config->format == AUDIO_FORMAT_DEFAULT)
5921 config->format = AUDIO_FORMAT_PCM_16_BIT;
5922 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5923 config->format = AUDIO_FORMAT_PCM_16_BIT;
5924 ret = -EINVAL;
5925 goto err_open;
5926 }
5927
5928 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5929 in->config = pcm_config_afe_proxy_record;
5930 in->config.channels = channel_count;
5931 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305932 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305933 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
5934 in, config, &channel_mask_updated)) {
5935 if (channel_mask_updated == true) {
5936 ALOGD("%s: return error to retry with updated channel mask (%#x)",
5937 __func__, config->channel_mask);
5938 ret = -EINVAL;
5939 goto err_open;
5940 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05305941 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07005942 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005943 audio_extn_compr_cap_format_supported(config->format) &&
5944 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005945 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305946 } else if (audio_extn_cin_applicable_stream(in)) {
5947 ret = audio_extn_cin_configure_input_stream(in);
5948 if (ret)
5949 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005950 } else {
5951 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005952 if (!in->realtime) {
5953 in->format = config->format;
5954 frame_size = audio_stream_in_frame_size(&in->stream);
5955 buffer_size = get_input_buffer_size(config->sample_rate,
5956 config->format,
5957 channel_count,
5958 is_low_latency);
5959 in->config.period_size = buffer_size / frame_size;
5960 }
5961
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005962#ifndef COMPRESS_VOIP_ENABLED
5963 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5964 (in->config.rate == 8000 || in->config.rate == 16000 ||
5965 in->config.rate == 32000 || in->config.rate == 48000) &&
5966 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5967
5968 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5969 in->config = default_pcm_config_voip_copp;
5970 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5971 in->config.rate = in->sample_rate;
5972#else
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005973 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
Haynes Mathew George16081042017-05-31 17:16:49 -07005974 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
5975 voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005976 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005977 (in->config.rate == 8000 || in->config.rate == 16000 ||
5978 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005979 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5980 voice_extn_compress_voip_open_input_stream(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005981#endif
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005982 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005983 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005984
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305985 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5986 &adev->streams_input_cfg_list,
5987 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305988 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305989
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005990 /* This stream could be for sound trigger lab,
5991 get sound trigger pcm if present */
5992 audio_extn_sound_trigger_check_and_get_session(in);
5993
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305994 lock_input_stream(in);
5995 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5996 pthread_mutex_lock(&adev->lock);
5997 in->card_status = adev->card_status;
5998 pthread_mutex_unlock(&adev->lock);
5999 pthread_mutex_unlock(&in->lock);
6000
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006001 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07006002 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006003 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006004
6005err_open:
6006 free(in);
6007 *stream_in = NULL;
6008 return ret;
6009}
6010
6011static void adev_close_input_stream(struct audio_hw_device *dev,
6012 struct audio_stream_in *stream)
6013{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006014 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006015 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006016 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306017
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306018 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006019
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306020 // must deregister from sndmonitor first to prevent races
6021 // between the callback and close_stream
6022 audio_extn_snd_mon_unregister_listener(stream);
6023
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306024 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07006025 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306026
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006027 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306028 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006029 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306030 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006031 if (ret != 0)
6032 ALOGE("%s: Compress voip input cannot be closed, error:%d",
6033 __func__, ret);
6034 } else
6035 in_standby(&stream->common);
6036
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07006037 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006038 audio_extn_ssr_deinit();
6039 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006040
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306041 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07006042 audio_extn_compr_cap_format_supported(in->config.format))
6043 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306044
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306045 if (audio_extn_cin_attached_usecase(in->usecase))
6046 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006047
Mingming Yinfd7607b2016-01-22 12:48:44 -08006048 if (in->is_st_session) {
6049 ALOGV("%s: sound trigger pcm stop lab", __func__);
6050 audio_extn_sound_trigger_stop_lab(in);
6051 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006052 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006053 return;
6054}
6055
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306056int adev_create_audio_patch(struct audio_hw_device *dev,
6057 unsigned int num_sources,
6058 const struct audio_port_config *sources,
6059 unsigned int num_sinks,
6060 const struct audio_port_config *sinks,
6061 audio_patch_handle_t *handle)
6062{
6063
6064
6065 return audio_extn_hw_loopback_create_audio_patch(dev,
6066 num_sources,
6067 sources,
6068 num_sinks,
6069 sinks,
6070 handle);
6071
6072}
6073
6074int adev_release_audio_patch(struct audio_hw_device *dev,
6075 audio_patch_handle_t handle)
6076{
6077 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
6078}
6079
6080int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
6081{
6082 return audio_extn_hw_loopback_get_audio_port(dev, config);
6083}
6084
6085int adev_set_audio_port_config(struct audio_hw_device *dev,
6086 const struct audio_port_config *config)
6087{
6088 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
6089}
6090
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006091static int adev_dump(const audio_hw_device_t *device __unused,
6092 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006093{
6094 return 0;
6095}
6096
6097static int adev_close(hw_device_t *device)
6098{
6099 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07006100
6101 if (!adev)
6102 return 0;
6103
6104 pthread_mutex_lock(&adev_init_lock);
6105
6106 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306107 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006108 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08006109 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306110 audio_extn_utils_release_streams_cfg_lists(
6111 &adev->streams_output_cfg_list,
6112 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306113 if (audio_extn_qaf_is_enabled())
6114 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006115 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006116 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006117 free(adev->snd_dev_ref_cnt);
6118 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006119 if (adev->adm_deinit)
6120 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306121 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006122 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306123 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306124 audio_extn_hw_loopback_deinit(adev);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306125 if (adev->device_cfg_params) {
6126 free(adev->device_cfg_params);
6127 adev->device_cfg_params = NULL;
6128 }
Kiran Kandi910e1862013-10-29 13:29:42 -07006129 free(device);
6130 adev = NULL;
6131 }
6132 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006134 return 0;
6135}
6136
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006137/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6138 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6139 * just that it _might_ work.
6140 */
6141static int period_size_is_plausible_for_low_latency(int period_size)
6142{
6143 switch (period_size) {
6144 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07006145 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006146 case 240:
6147 case 320:
6148 case 480:
6149 return 1;
6150 default:
6151 return 0;
6152 }
6153}
6154
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306155static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
6156{
6157 bool is_snd_card_status = false;
6158 bool is_ext_device_status = false;
6159 char value[32];
6160 int card = -1;
6161 card_status_t status;
6162
6163 if (cookie != adev || !parms)
6164 return;
6165
6166 if (!parse_snd_card_status(parms, &card, &status)) {
6167 is_snd_card_status = true;
6168 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
6169 is_ext_device_status = true;
6170 } else {
6171 // not a valid event
6172 return;
6173 }
6174
6175 pthread_mutex_lock(&adev->lock);
6176 if (card == adev->snd_card || is_ext_device_status) {
6177 if (is_snd_card_status && adev->card_status != status) {
6178 adev->card_status = status;
6179 platform_snd_card_update(adev->platform, status);
6180 audio_extn_fm_set_parameters(adev, parms);
6181 } else if (is_ext_device_status) {
6182 platform_set_parameters(adev->platform, parms);
6183 }
6184 }
6185 pthread_mutex_unlock(&adev->lock);
6186 return;
6187}
6188
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306189/* out and adev lock held */
6190static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6191{
6192 struct audio_usecase *uc_info;
6193 float left_p;
6194 float right_p;
6195 audio_devices_t devices;
6196
6197 uc_info = get_usecase_from_list(adev, out->usecase);
6198 if (uc_info == NULL) {
6199 ALOGE("%s: Could not find the usecase (%d) in the list",
6200 __func__, out->usecase);
6201 return -EINVAL;
6202 }
6203
6204 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6205 out->usecase, use_case_table[out->usecase]);
6206
6207 if (restore) {
6208 // restore A2DP device for active usecases and unmute if required
6209 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6210 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
6211 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
6212 select_devices(adev, uc_info->id);
6213 pthread_mutex_lock(&out->compr_mute_lock);
6214 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6215 (out->a2dp_compress_mute)) {
6216 out->a2dp_compress_mute = false;
6217 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6218 }
6219 pthread_mutex_unlock(&out->compr_mute_lock);
6220 }
6221 } else {
6222 // mute compress stream if suspended
6223 pthread_mutex_lock(&out->compr_mute_lock);
6224 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6225 (!out->a2dp_compress_mute)) {
6226 if (!out->standby) {
6227 ALOGD("%s: selecting speaker and muting stream", __func__);
6228 devices = out->devices;
6229 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6230 left_p = out->volume_l;
6231 right_p = out->volume_r;
6232 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6233 compress_pause(out->compr);
6234 out_set_compr_volume(&out->stream, (float)0, (float)0);
6235 out->a2dp_compress_mute = true;
6236 select_devices(adev, out->usecase);
6237 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6238 compress_resume(out->compr);
6239 out->devices = devices;
6240 out->volume_l = left_p;
6241 out->volume_r = right_p;
6242 }
6243 }
6244 pthread_mutex_unlock(&out->compr_mute_lock);
6245 }
6246 ALOGV("%s: exit", __func__);
6247 return 0;
6248}
6249
6250int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6251{
6252 int ret = 0;
6253
6254 lock_output_stream(out);
6255 pthread_mutex_lock(&adev->lock);
6256
6257 ret = check_a2dp_restore_l(adev, out, restore);
6258
6259 pthread_mutex_unlock(&adev->lock);
6260 pthread_mutex_unlock(&out->lock);
6261 return ret;
6262}
6263
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006264static int adev_open(const hw_module_t *module, const char *name,
6265 hw_device_t **device)
6266{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306267 int ret;
6268
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006269 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006270 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
6271
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006272 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07006273 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006274 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07006275 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006276 ALOGD("%s: returning existing instance of adev", __func__);
6277 ALOGD("%s: exit", __func__);
6278 pthread_mutex_unlock(&adev_init_lock);
6279 return 0;
6280 }
6281
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006282 adev = calloc(1, sizeof(struct audio_device));
6283
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006284 if (!adev) {
6285 pthread_mutex_unlock(&adev_init_lock);
6286 return -ENOMEM;
6287 }
6288
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006289 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6290
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05306291#ifdef DYNAMIC_LOG_ENABLED
6292 register_for_dynamic_logging("hal");
6293#endif
6294
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006295 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6296 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6297 adev->device.common.module = (struct hw_module_t *)module;
6298 adev->device.common.close = adev_close;
6299
6300 adev->device.init_check = adev_init_check;
6301 adev->device.set_voice_volume = adev_set_voice_volume;
6302 adev->device.set_master_volume = adev_set_master_volume;
6303 adev->device.get_master_volume = adev_get_master_volume;
6304 adev->device.set_master_mute = adev_set_master_mute;
6305 adev->device.get_master_mute = adev_get_master_mute;
6306 adev->device.set_mode = adev_set_mode;
6307 adev->device.set_mic_mute = adev_set_mic_mute;
6308 adev->device.get_mic_mute = adev_get_mic_mute;
6309 adev->device.set_parameters = adev_set_parameters;
6310 adev->device.get_parameters = adev_get_parameters;
6311 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6312 adev->device.open_output_stream = adev_open_output_stream;
6313 adev->device.close_output_stream = adev_close_output_stream;
6314 adev->device.open_input_stream = adev_open_input_stream;
6315 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306316 adev->device.create_audio_patch = adev_create_audio_patch;
6317 adev->device.release_audio_patch = adev_release_audio_patch;
6318 adev->device.get_audio_port = adev_get_audio_port;
6319 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006320 adev->device.dump = adev_dump;
6321
6322 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006323 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08006324 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006325 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006326 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006327 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006328 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07006329 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306330 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006331 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006332 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006333 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006334 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08006335 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006336 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05306337 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306338 adev->perf_lock_opts[0] = 0x101;
6339 adev->perf_lock_opts[1] = 0x20E;
6340 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306341
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006342 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006343 adev->platform = platform_init(adev);
6344 if (!adev->platform) {
6345 free(adev->snd_dev_ref_cnt);
6346 free(adev);
6347 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6348 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08006349 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306350 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006351 return -EINVAL;
6352 }
Eric Laurentc4aef752013-09-12 17:45:53 -07006353
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306354 if (audio_extn_qaf_is_enabled()) {
6355 ret = audio_extn_qaf_init(adev);
6356 if (ret < 0) {
6357 free(adev);
6358 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6359 *device = NULL;
6360 pthread_mutex_unlock(&adev_init_lock);
6361 pthread_mutex_destroy(&adev->lock);
6362 return ret;
6363 }
6364
6365 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
6366 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
6367 }
6368
Eric Laurentc4aef752013-09-12 17:45:53 -07006369 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
6370 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6371 if (adev->visualizer_lib == NULL) {
6372 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6373 } else {
6374 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6375 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006376 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006377 "visualizer_hal_start_output");
6378 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006379 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006380 "visualizer_hal_stop_output");
6381 }
6382 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05306383 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08006384 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006385 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306386 audio_extn_hw_loopback_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07006387
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006388 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
6389 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6390 if (adev->offload_effects_lib == NULL) {
6391 ALOGE("%s: DLOPEN failed for %s", __func__,
6392 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6393 } else {
6394 ALOGV("%s: DLOPEN successful for %s", __func__,
6395 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6396 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05306397 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006398 "offload_effects_bundle_hal_start_output");
6399 adev->offload_effects_stop_output =
6400 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6401 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006402 adev->offload_effects_set_hpx_state =
6403 (int (*)(bool))dlsym(adev->offload_effects_lib,
6404 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05306405 adev->offload_effects_get_parameters =
6406 (void (*)(struct str_parms *, struct str_parms *))
6407 dlsym(adev->offload_effects_lib,
6408 "offload_effects_bundle_get_parameters");
6409 adev->offload_effects_set_parameters =
6410 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
6411 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006412 }
6413 }
6414
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006415 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
6416 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6417 if (adev->adm_lib == NULL) {
6418 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6419 } else {
6420 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6421 adev->adm_init = (adm_init_t)
6422 dlsym(adev->adm_lib, "adm_init");
6423 adev->adm_deinit = (adm_deinit_t)
6424 dlsym(adev->adm_lib, "adm_deinit");
6425 adev->adm_register_input_stream = (adm_register_input_stream_t)
6426 dlsym(adev->adm_lib, "adm_register_input_stream");
6427 adev->adm_register_output_stream = (adm_register_output_stream_t)
6428 dlsym(adev->adm_lib, "adm_register_output_stream");
6429 adev->adm_deregister_stream = (adm_deregister_stream_t)
6430 dlsym(adev->adm_lib, "adm_deregister_stream");
6431 adev->adm_request_focus = (adm_request_focus_t)
6432 dlsym(adev->adm_lib, "adm_request_focus");
6433 adev->adm_abandon_focus = (adm_abandon_focus_t)
6434 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006435 adev->adm_set_config = (adm_set_config_t)
6436 dlsym(adev->adm_lib, "adm_set_config");
6437 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6438 dlsym(adev->adm_lib, "adm_request_focus_v2");
6439 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6440 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6441 adev->adm_on_routing_change = (adm_on_routing_change_t)
6442 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006443 }
6444 }
6445
Mingming Yin514a8bc2014-07-29 15:22:21 -07006446 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006447 //initialize this to false for now,
6448 //this will be set to true through set param
6449 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07006450
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07006451 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006452 *device = &adev->device.common;
6453
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306454 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
6455 &adev->streams_output_cfg_list,
6456 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006457
Kiran Kandi910e1862013-10-29 13:29:42 -07006458 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006459
6460 char value[PROPERTY_VALUE_MAX];
6461 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006462 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006463 trial = atoi(value);
6464 if (period_size_is_plausible_for_low_latency(trial)) {
6465 pcm_config_low_latency.period_size = trial;
6466 pcm_config_low_latency.start_threshold = trial / 4;
6467 pcm_config_low_latency.avail_min = trial / 4;
6468 configured_low_latency_capture_period_size = trial;
6469 }
6470 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006471 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006472 trial = atoi(value);
6473 if (period_size_is_plausible_for_low_latency(trial)) {
6474 configured_low_latency_capture_period_size = trial;
6475 }
6476 }
6477
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006478 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006479 af_period_multiplier = atoi(value);
6480 if (af_period_multiplier < 0)
6481 af_period_multiplier = 2;
6482 else if (af_period_multiplier > 4)
6483 af_period_multiplier = 4;
6484
6485 ALOGV("new period_multiplier = %d", af_period_multiplier);
6486 }
6487
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006488 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006489 pthread_mutex_unlock(&adev_init_lock);
6490
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006491 if (adev->adm_init)
6492 adev->adm_data = adev->adm_init();
6493
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306494 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306495 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006496 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306497
6498 audio_extn_snd_mon_init();
6499 pthread_mutex_lock(&adev->lock);
6500 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
6501 adev->card_status = CARD_STATUS_ONLINE;
6502 pthread_mutex_unlock(&adev->lock);
6503 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306504 /* Allocate memory for Device config params */
6505 adev->device_cfg_params = (struct audio_device_config_param*)
6506 calloc(platform_get_max_codec_backend(),
6507 sizeof(struct audio_device_config_param));
6508 if (adev->device_cfg_params == NULL)
6509 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306510
Eric Laurent994a6932013-07-17 11:51:42 -07006511 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006512 return 0;
6513}
6514
6515static struct hw_module_methods_t hal_module_methods = {
6516 .open = adev_open,
6517};
6518
6519struct audio_module HAL_MODULE_INFO_SYM = {
6520 .common = {
6521 .tag = HARDWARE_MODULE_TAG,
6522 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6523 .hal_api_version = HARDWARE_HAL_API_VERSION,
6524 .id = AUDIO_HARDWARE_MODULE_ID,
6525 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08006526 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006527 .methods = &hal_module_methods,
6528 },
6529};