blob: ca891ac378928f8f7d52a087c672486d11ad6a70 [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 = "";
4131
4132 ALOGV("%s", __func__);
4133 pthread_mutex_lock(&adev->lock);
4134
4135 if (info == NULL || min_size_frames == 0) {
4136 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
4137 ret = -EINVAL;
4138 goto exit;
4139 }
4140 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
4141 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
4142 ret = -ENOSYS;
4143 goto exit;
4144 }
4145 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4146 if (out->pcm_device_id < 0) {
4147 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4148 __func__, out->pcm_device_id, out->usecase);
4149 ret = -EINVAL;
4150 goto exit;
4151 }
4152
4153 adjust_mmap_period_count(&out->config, min_size_frames);
4154
4155 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4156 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
4157 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
4158 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
4159 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4160 step = "open";
4161 ret = -ENODEV;
4162 goto exit;
4163 }
4164 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
4165 if (ret < 0) {
4166 step = "begin";
4167 goto exit;
4168 }
4169 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
4170 info->burst_size_frames = out->config.period_size;
4171 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
4172
4173 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
4174 info->buffer_size_frames));
4175
4176 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
4177 if (ret < 0) {
4178 step = "commit";
4179 goto exit;
4180 }
4181
4182 out->standby = false;
4183 ret = 0;
4184
4185 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4186 __func__, info->shared_memory_address, info->buffer_size_frames);
4187
4188exit:
4189 if (ret != 0) {
4190 if (out->pcm == NULL) {
4191 ALOGE("%s: %s - %d", __func__, step, ret);
4192 } else {
4193 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
4194 pcm_close(out->pcm);
4195 out->pcm = NULL;
4196 }
4197 }
4198 pthread_mutex_unlock(&adev->lock);
4199 return ret;
4200}
4201
4202static int out_get_mmap_position(const struct audio_stream_out *stream,
4203 struct audio_mmap_position *position)
4204{
4205 struct stream_out *out = (struct stream_out *)stream;
4206 ALOGVV("%s", __func__);
4207 if (position == NULL) {
4208 return -EINVAL;
4209 }
4210 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
4211 return -ENOSYS;
4212 }
4213 if (out->pcm == NULL) {
4214 return -ENOSYS;
4215 }
4216
4217 struct timespec ts = { 0, 0 };
4218 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
4219 if (ret < 0) {
4220 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
4221 return ret;
4222 }
4223 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4224 return 0;
4225}
4226
4227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004228/** audio_stream_in implementation **/
4229static uint32_t in_get_sample_rate(const struct audio_stream *stream)
4230{
4231 struct stream_in *in = (struct stream_in *)stream;
4232
4233 return in->config.rate;
4234}
4235
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004236static int in_set_sample_rate(struct audio_stream *stream __unused,
4237 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004238{
4239 return -ENOSYS;
4240}
4241
4242static size_t in_get_buffer_size(const struct audio_stream *stream)
4243{
4244 struct stream_in *in = (struct stream_in *)stream;
4245
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004246 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
4247 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004248 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
4249 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 -07004250 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
4251 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304252 else if(audio_extn_cin_attached_usecase(in->usecase))
4253 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004254
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004255 return in->config.period_size * in->af_period_multiplier *
4256 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004257}
4258
4259static uint32_t in_get_channels(const struct audio_stream *stream)
4260{
4261 struct stream_in *in = (struct stream_in *)stream;
4262
4263 return in->channel_mask;
4264}
4265
4266static audio_format_t in_get_format(const struct audio_stream *stream)
4267{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004268 struct stream_in *in = (struct stream_in *)stream;
4269
4270 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004271}
4272
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004273static int in_set_format(struct audio_stream *stream __unused,
4274 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004275{
4276 return -ENOSYS;
4277}
4278
4279static int in_standby(struct audio_stream *stream)
4280{
4281 struct stream_in *in = (struct stream_in *)stream;
4282 struct audio_device *adev = in->dev;
4283 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304284 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4285 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07004286 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304287
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004288 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004289 if (!in->standby && in->is_st_session) {
4290 ALOGD("%s: sound trigger pcm stop lab", __func__);
4291 audio_extn_sound_trigger_stop_lab(in);
4292 in->standby = 1;
4293 }
4294
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004295 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004296 if (adev->adm_deregister_stream)
4297 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
4298
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004299 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004300 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004301 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
4302 voice_extn_compress_voip_close_input_stream(stream);
4303 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07004304 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4305 do_stop = in->capture_started;
4306 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08004307 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304308 if (audio_extn_cin_attached_usecase(in->usecase))
4309 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08004310 if (in->pcm) {
4311 pcm_close(in->pcm);
4312 in->pcm = NULL;
4313 }
4314 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004315 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004316 if (in->pcm) {
4317 pcm_close(in->pcm);
4318 in->pcm = NULL;
4319 }
4320
4321 if (do_stop) {
4322 status = stop_input_stream(in);
4323 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004324 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004325 }
4326 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07004327 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004328 return status;
4329}
4330
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004331static int in_dump(const struct audio_stream *stream __unused,
4332 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004333{
4334 return 0;
4335}
4336
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304337static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4338{
4339 if (!stream || !parms)
4340 return;
4341
4342 struct stream_in *in = (struct stream_in *)stream;
4343 struct audio_device *adev = in->dev;
4344
4345 card_status_t status;
4346 int card;
4347 if (parse_snd_card_status(parms, &card, &status) < 0)
4348 return;
4349
4350 pthread_mutex_lock(&adev->lock);
4351 bool valid_cb = (card == adev->snd_card);
4352 pthread_mutex_unlock(&adev->lock);
4353
4354 if (!valid_cb)
4355 return;
4356
4357 lock_input_stream(in);
4358 if (in->card_status != status)
4359 in->card_status = status;
4360 pthread_mutex_unlock(&in->lock);
4361
4362 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4363 use_case_table[in->usecase],
4364 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4365
4366 // a better solution would be to report error back to AF and let
4367 // it put the stream to standby
4368 if (status == CARD_STATUS_OFFLINE)
4369 in_standby(&in->stream.common);
4370
4371 return;
4372}
4373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004374static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4375{
4376 struct stream_in *in = (struct stream_in *)stream;
4377 struct audio_device *adev = in->dev;
4378 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004379 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004380 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304382 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004383 parms = str_parms_create_str(kvpairs);
4384
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304385 if (!parms)
4386 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004387 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004388 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004389
4390 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4391 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004392 val = atoi(value);
4393 /* no audio source uses val == 0 */
4394 if ((in->source != val) && (val != 0)) {
4395 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004396 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4397 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4398 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004399 (in->config.rate == 8000 || in->config.rate == 16000 ||
4400 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004401 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004402 err = voice_extn_compress_voip_open_input_stream(in);
4403 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004404 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004405 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004406 }
4407 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004408 }
4409 }
4410
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004411 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4412 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004413 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004414 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004415 in->device = val;
4416 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004417 if (!in->standby && !in->is_st_session) {
4418 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07004419 if (adev->adm_on_routing_change)
4420 adev->adm_on_routing_change(adev->adm_data,
4421 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004422 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004423 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004424 }
4425 }
4426
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304427 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4428 if (err >= 0) {
4429 strlcpy(in->profile, value, sizeof(in->profile));
4430 ALOGV("updating stream profile with value '%s'", in->profile);
4431 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4432 &adev->streams_input_cfg_list,
4433 in->device, in->flags, in->format,
4434 in->sample_rate, in->bit_width,
4435 in->profile, &in->app_type_cfg);
4436 }
4437
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004438 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004439 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004440
4441 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304442error:
Eric Laurent994a6932013-07-17 11:51:42 -07004443 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004444 return ret;
4445}
4446
4447static char* in_get_parameters(const struct audio_stream *stream,
4448 const char *keys)
4449{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004450 struct stream_in *in = (struct stream_in *)stream;
4451 struct str_parms *query = str_parms_create_str(keys);
4452 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004453 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004454
4455 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004456 if (reply) {
4457 str_parms_destroy(reply);
4458 }
4459 if (query) {
4460 str_parms_destroy(query);
4461 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004462 ALOGE("in_get_parameters: failed to create query or reply");
4463 return NULL;
4464 }
4465
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004466 ALOGV("%s: enter: keys - %s", __func__, keys);
4467
4468 voice_extn_in_get_parameters(in, query, reply);
4469
4470 str = str_parms_to_str(reply);
4471 str_parms_destroy(query);
4472 str_parms_destroy(reply);
4473
4474 ALOGV("%s: exit: returns - %s", __func__, str);
4475 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004476}
4477
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004478static int in_set_gain(struct audio_stream_in *stream __unused,
4479 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004480{
4481 return 0;
4482}
4483
4484static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4485 size_t bytes)
4486{
4487 struct stream_in *in = (struct stream_in *)stream;
4488 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304489 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304490 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004491
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004492 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304493
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004494 if (in->is_st_session) {
4495 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
4496 /* Read from sound trigger HAL */
4497 audio_extn_sound_trigger_read(in, buffer, bytes);
4498 pthread_mutex_unlock(&in->lock);
4499 return bytes;
4500 }
4501
Haynes Mathew George16081042017-05-31 17:16:49 -07004502 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4503 ret = -ENOSYS;
4504 goto exit;
4505 }
4506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004507 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004508 pthread_mutex_lock(&adev->lock);
4509 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
4510 ret = voice_extn_compress_voip_start_input_stream(in);
4511 else
4512 ret = start_input_stream(in);
4513 pthread_mutex_unlock(&adev->lock);
4514 if (ret != 0) {
4515 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004516 }
4517 in->standby = 0;
4518 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004519
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004520 // what's the duration requested by the client?
4521 long ns = 0;
4522
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304523 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004524 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4525 in->config.rate;
4526
4527 request_in_focus(in, ns);
4528 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004529
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304530 if (audio_extn_cin_attached_usecase(in->usecase)) {
4531 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
4532 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304533 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004534 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304535 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07004536 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004537 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004538 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304539 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004540 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304541 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4542 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4543 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
4544 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304545 ret = -EINVAL;
4546 goto exit;
4547 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304548 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304549 ret = -errno;
4550 }
4551 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304552 /* bytes read is always set to bytes for non compress usecases */
4553 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004554 }
4555
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004556 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004558 /*
4559 * Instead of writing zeroes here, we could trust the hardware
4560 * to always provide zeroes when muted.
4561 */
Pavan Chikkala63964842014-12-04 10:48:28 +05304562 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
4563 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004564 memset(buffer, 0, bytes);
4565
4566exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004567 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304568 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004569 pthread_mutex_unlock(&in->lock);
4570
4571 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304572 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304573 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304574 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304575 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304576 in->standby = true;
4577 }
Sharad Sangled17c9122017-03-20 15:58:52 +05304578 if (!audio_extn_cin_attached_usecase(in->usecase)) {
4579 bytes_read = bytes;
4580 memset(buffer, 0, bytes);
4581 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004582 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004583 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05304584 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05304585 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004586 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304587 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588}
4589
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004590static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004591{
4592 return 0;
4593}
4594
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004595static int add_remove_audio_effect(const struct audio_stream *stream,
4596 effect_handle_t effect,
4597 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004598{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004599 struct stream_in *in = (struct stream_in *)stream;
4600 int status = 0;
4601 effect_descriptor_t desc;
4602
4603 status = (*effect)->get_descriptor(effect, &desc);
4604 if (status != 0)
4605 return status;
4606
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004607 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004608 pthread_mutex_lock(&in->dev->lock);
4609 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4610 in->enable_aec != enable &&
4611 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4612 in->enable_aec = enable;
4613 if (!in->standby)
4614 select_devices(in->dev, in->usecase);
4615 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08004616 if (in->enable_ns != enable &&
4617 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4618 in->enable_ns = enable;
4619 if (!in->standby)
4620 select_devices(in->dev, in->usecase);
4621 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004622 pthread_mutex_unlock(&in->dev->lock);
4623 pthread_mutex_unlock(&in->lock);
4624
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004625 return 0;
4626}
4627
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004628static int in_add_audio_effect(const struct audio_stream *stream,
4629 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004630{
Eric Laurent994a6932013-07-17 11:51:42 -07004631 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004632 return add_remove_audio_effect(stream, effect, true);
4633}
4634
4635static int in_remove_audio_effect(const struct audio_stream *stream,
4636 effect_handle_t effect)
4637{
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, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004640}
4641
Haynes Mathew George16081042017-05-31 17:16:49 -07004642static int in_stop(const struct audio_stream_in* stream)
4643{
4644 struct stream_in *in = (struct stream_in *)stream;
4645 struct audio_device *adev = in->dev;
4646
4647 int ret = -ENOSYS;
4648 ALOGV("%s", __func__);
4649 pthread_mutex_lock(&adev->lock);
4650 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4651 in->capture_started && in->pcm != NULL) {
4652 pcm_stop(in->pcm);
4653 ret = stop_input_stream(in);
4654 in->capture_started = false;
4655 }
4656 pthread_mutex_unlock(&adev->lock);
4657 return ret;
4658}
4659
4660static int in_start(const struct audio_stream_in* stream)
4661{
4662 struct stream_in *in = (struct stream_in *)stream;
4663 struct audio_device *adev = in->dev;
4664 int ret = -ENOSYS;
4665
4666 ALOGV("%s in %p", __func__, in);
4667 pthread_mutex_lock(&adev->lock);
4668 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4669 !in->capture_started && in->pcm != NULL) {
4670 if (!in->capture_started) {
4671 ret = start_input_stream(in);
4672 if (ret == 0) {
4673 in->capture_started = true;
4674 }
4675 }
4676 }
4677 pthread_mutex_unlock(&adev->lock);
4678 return ret;
4679}
4680
4681static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4682 int32_t min_size_frames,
4683 struct audio_mmap_buffer_info *info)
4684{
4685 struct stream_in *in = (struct stream_in *)stream;
4686 struct audio_device *adev = in->dev;
4687 int ret = 0;
4688 unsigned int offset1;
4689 unsigned int frames1;
4690 const char *step = "";
4691
4692 pthread_mutex_lock(&adev->lock);
4693 ALOGV("%s in %p", __func__, in);
4694
4695 if (info == NULL || min_size_frames == 0) {
4696 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
4697 ret = -EINVAL;
4698 goto exit;
4699 }
4700 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
4701 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
4702 ALOGV("%s in %p", __func__, in);
4703 ret = -ENOSYS;
4704 goto exit;
4705 }
4706 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4707 if (in->pcm_device_id < 0) {
4708 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4709 __func__, in->pcm_device_id, in->usecase);
4710 ret = -EINVAL;
4711 goto exit;
4712 }
4713
4714 adjust_mmap_period_count(&in->config, min_size_frames);
4715
4716 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4717 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4718 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4719 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4720 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4721 step = "open";
4722 ret = -ENODEV;
4723 goto exit;
4724 }
4725
4726 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4727 if (ret < 0) {
4728 step = "begin";
4729 goto exit;
4730 }
4731 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
4732 info->burst_size_frames = in->config.period_size;
4733 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4734
4735 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
4736 info->buffer_size_frames));
4737
4738 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4739 if (ret < 0) {
4740 step = "commit";
4741 goto exit;
4742 }
4743
4744 in->standby = false;
4745 ret = 0;
4746
4747 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4748 __func__, info->shared_memory_address, info->buffer_size_frames);
4749
4750exit:
4751 if (ret != 0) {
4752 if (in->pcm == NULL) {
4753 ALOGE("%s: %s - %d", __func__, step, ret);
4754 } else {
4755 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
4756 pcm_close(in->pcm);
4757 in->pcm = NULL;
4758 }
4759 }
4760 pthread_mutex_unlock(&adev->lock);
4761 return ret;
4762}
4763
4764static int in_get_mmap_position(const struct audio_stream_in *stream,
4765 struct audio_mmap_position *position)
4766{
4767 struct stream_in *in = (struct stream_in *)stream;
4768 ALOGVV("%s", __func__);
4769 if (position == NULL) {
4770 return -EINVAL;
4771 }
4772 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
4773 return -ENOSYS;
4774 }
4775 if (in->pcm == NULL) {
4776 return -ENOSYS;
4777 }
4778 struct timespec ts = { 0, 0 };
4779 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
4780 if (ret < 0) {
4781 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
4782 return ret;
4783 }
4784 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4785 return 0;
4786}
4787
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304788int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07004789 audio_io_handle_t handle,
4790 audio_devices_t devices,
4791 audio_output_flags_t flags,
4792 struct audio_config *config,
4793 struct audio_stream_out **stream_out,
4794 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004795{
4796 struct audio_device *adev = (struct audio_device *)dev;
4797 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304798 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004799 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004800 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004802 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004804 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4805
Mingming Yin3a941d42016-02-17 18:08:05 -08004806 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
4807 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304808 devices, flags, &out->stream);
4809
4810
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004811 if (!out) {
4812 return -ENOMEM;
4813 }
4814
Haynes Mathew George204045b2015-02-25 20:32:03 -08004815 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004816 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304817 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08004818 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4819
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004820 if (devices == AUDIO_DEVICE_NONE)
4821 devices = AUDIO_DEVICE_OUT_SPEAKER;
4822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004823 out->flags = flags;
4824 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004825 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004826 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004827 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05304828 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05304829 if (out->channel_mask == AUDIO_CHANNEL_NONE)
4830 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
4831 else
4832 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07004833 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004834 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08004835 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304836 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304837 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304838 out->a2dp_compress_mute = false;
Alexy Joseph98988832017-01-13 14:56:59 -08004839 out->dynamic_pm_qos_enabled = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004840
Mingming Yin3a941d42016-02-17 18:08:05 -08004841 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4842 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
4843 pthread_mutex_lock(&adev->lock);
4844 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
4845 ret = read_hdmi_sink_caps(out);
4846 pthread_mutex_unlock(&adev->lock);
4847 if (ret != 0) {
4848 if (ret == -ENOSYS) {
4849 /* ignore and go with default */
4850 ret = 0;
4851 } else {
4852 ALOGE("error reading hdmi sink caps");
4853 goto error_open;
4854 }
4855 }
4856 }
4857
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004858 /* Init use case and pcm_config */
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004859#ifndef COMPRESS_VOIP_ENABLED
4860 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4861 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
4862 out->sample_rate == 32000 || out->sample_rate == 48000)) {
4863 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
4864 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
4865 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4866
4867 out->config = default_pcm_config_voip_copp;
4868 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
4869 out->config.rate = out->sample_rate;
4870
4871#else
Dhananjay Kumarac341582017-02-23 23:42:25 +05304872 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004873 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08004874 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004875 ret = voice_extn_compress_voip_open_output_stream(out);
4876 if (ret != 0) {
4877 ALOGE("%s: Compress voip output cannot be opened, error:%d",
4878 __func__, ret);
4879 goto error_open;
4880 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004881#endif
vivek mehta0ea887a2015-08-26 14:01:20 -07004882 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304883 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304884 pthread_mutex_lock(&adev->lock);
4885 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4886 pthread_mutex_unlock(&adev->lock);
4887
4888 // reject offload during card offline to allow
4889 // fallback to s/w paths
4890 if (offline) {
4891 ret = -ENODEV;
4892 goto error_open;
4893 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004894
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004895 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4896 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4897 ALOGE("%s: Unsupported Offload information", __func__);
4898 ret = -EINVAL;
4899 goto error_open;
4900 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004901
Mingming Yin3a941d42016-02-17 18:08:05 -08004902 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004903 if(config->offload_info.format == 0)
4904 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004905 if (config->offload_info.sample_rate == 0)
4906 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004907 }
4908
Mingming Yin90310102013-11-13 16:57:00 -08004909 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304910 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004911 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004912 ret = -EINVAL;
4913 goto error_open;
4914 }
4915
Ben Romberger0f8c87b2017-05-24 17:41:11 -07004916 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
4917 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
4918 (audio_extn_passthru_is_passthrough_stream(out)) &&
4919 !((config->sample_rate == 48000) ||
4920 (config->sample_rate == 96000) ||
4921 (config->sample_rate == 192000))) {
4922 ALOGE("%s: Unsupported sample rate %d for audio format %x",
4923 __func__, config->sample_rate, config->offload_info.format);
4924 ret = -EINVAL;
4925 goto error_open;
4926 }
4927
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004928 out->compr_config.codec = (struct snd_codec *)
4929 calloc(1, sizeof(struct snd_codec));
4930
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004931 if (!out->compr_config.codec) {
4932 ret = -ENOMEM;
4933 goto error_open;
4934 }
4935
Dhananjay Kumarac341582017-02-23 23:42:25 +05304936 out->stream.pause = out_pause;
4937 out->stream.resume = out_resume;
4938 out->stream.flush = out_flush;
4939 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004940 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004941 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304942 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004943 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304944 } else {
4945 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4946 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004947 }
vivek mehta446c3962015-09-14 10:57:35 -07004948
4949 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004950 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4951 config->format == 0 && config->sample_rate == 0 &&
4952 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004953 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004954 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4955 } else {
4956 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4957 ret = -EEXIST;
4958 goto error_open;
4959 }
vivek mehta446c3962015-09-14 10:57:35 -07004960 }
4961
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004962 if (config->offload_info.channel_mask)
4963 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004964 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004965 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004966 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004967 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304968 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004969 ret = -EINVAL;
4970 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004971 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004972
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004973 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004974 out->sample_rate = config->offload_info.sample_rate;
4975
Mingming Yin3ee55c62014-08-04 14:23:35 -07004976 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004977
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304978 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4979 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4980 audio_extn_dolby_send_ddp_endp_params(adev);
4981 audio_extn_dolby_set_dmid(adev);
4982 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004983
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004984 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004985 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004986 out->compr_config.codec->bit_rate =
4987 config->offload_info.bit_rate;
4988 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304989 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004990 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304991 /* Update bit width only for non passthrough usecases.
4992 * For passthrough usecases, the output will always be opened @16 bit
4993 */
4994 if (!audio_extn_passthru_is_passthrough_stream(out))
4995 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304996
4997 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4998 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
4999 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
5000
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005001 /*TODO: Do we need to change it for passthrough */
5002 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005003
Manish Dewangana6fc5442015-08-24 20:30:31 +05305004 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
5005 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305006 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05305007 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305008 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
5009 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305010
5011 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
5012 AUDIO_FORMAT_PCM) {
5013
5014 /*Based on platform support, configure appropriate alsa format for corresponding
5015 *hal input format.
5016 */
5017 out->compr_config.codec->format = hal_format_to_alsa(
5018 config->offload_info.format);
5019
Ashish Jain83a6cc22016-06-28 14:34:17 +05305020 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05305021 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305022 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305023
Dhananjay Kumarac341582017-02-23 23:42:25 +05305024 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05305025 *hal input format and alsa format might differ based on platform support.
5026 */
5027 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05305028 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305029
5030 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
5031
5032 /* Check if alsa session is configured with the same format as HAL input format,
5033 * if not then derive correct fragment size needed to accomodate the
5034 * conversion of HAL input format to alsa format.
5035 */
5036 audio_extn_utils_update_direct_pcm_fragment_size(out);
5037
5038 /*if hal input and output fragment size is different this indicates HAL input format is
5039 *not same as the alsa format
5040 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305041 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305042 /*Allocate a buffer to convert input data to the alsa configured format.
5043 *size of convert buffer is equal to the size required to hold one fragment size
5044 *worth of pcm data, this is because flinger does not write more than fragment_size
5045 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305046 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
5047 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05305048 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
5049 ret = -ENOMEM;
5050 goto error_open;
5051 }
5052 }
5053 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
5054 out->compr_config.fragment_size =
5055 audio_extn_passthru_get_buffer_size(&config->offload_info);
5056 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5057 } else {
5058 out->compr_config.fragment_size =
5059 platform_get_compress_offload_buffer_size(&config->offload_info);
5060 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5061 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07005062
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305063 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5064 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
5065 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07005066 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05305067 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005068
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05305069 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
5070 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
5071 }
5072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005073 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
5074 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005075
Manish Dewangan69426c82017-01-30 17:35:36 +05305076 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
5077 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
5078 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
5079 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5080 out->render_mode = RENDER_MODE_AUDIO_MASTER;
5081 } else {
5082 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
5083 }
Alexy Josephaa54c872014-12-03 02:46:47 -08005084
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05305085 memset(&out->channel_map_param, 0,
5086 sizeof(struct audio_out_channel_map_param));
5087
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005088 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305089 out->send_next_track_params = false;
5090 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005091 out->offload_state = OFFLOAD_STATE_IDLE;
5092 out->playback_started = 0;
5093
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005094 audio_extn_dts_create_state_notifier_node(out->usecase);
5095
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005096 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
5097 __func__, config->offload_info.version,
5098 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05305099
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305100 /* Check if DSD audio format is supported in codec
5101 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305102 */
5103
5104 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305105 (!platform_check_codec_dsd_support(adev->platform) ||
5106 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305107 ret = -EINVAL;
5108 goto error_open;
5109 }
5110
Ashish Jain5106d362016-05-11 19:23:33 +05305111 /* Disable gapless if any of the following is true
5112 * passthrough playback
5113 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05305114 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05305115 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305116 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305117 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07005118 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305119 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305120 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05305121 check_and_set_gapless_mode(adev, false);
5122 } else
5123 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07005124
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305125 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07005126 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5127 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305128 if (config->format == AUDIO_FORMAT_DSD) {
5129 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5130 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
5131 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07005132
5133 create_offload_callback_thread(out);
5134
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005135 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305136 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005137 if (ret != 0) {
5138 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
5139 __func__, ret);
5140 goto error_open;
5141 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005142 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
5143 if (config->sample_rate == 0)
5144 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5145 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5146 config->sample_rate != 8000) {
5147 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5148 ret = -EINVAL;
5149 goto error_open;
5150 }
5151 out->sample_rate = config->sample_rate;
5152 out->config.rate = config->sample_rate;
5153 if (config->format == AUDIO_FORMAT_DEFAULT)
5154 config->format = AUDIO_FORMAT_PCM_16_BIT;
5155 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5156 config->format = AUDIO_FORMAT_PCM_16_BIT;
5157 ret = -EINVAL;
5158 goto error_open;
5159 }
5160 out->format = config->format;
5161 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
5162 out->config = pcm_config_afe_proxy_playback;
5163 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005164 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05305165 unsigned int channels = 0;
5166 /*Update config params to default if not set by the caller*/
5167 if (config->sample_rate == 0)
5168 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5169 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5170 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5171 if (config->format == AUDIO_FORMAT_DEFAULT)
5172 config->format = AUDIO_FORMAT_PCM_16_BIT;
5173
5174 channels = audio_channel_count_from_out_mask(out->channel_mask);
5175
Ashish Jain83a6cc22016-06-28 14:34:17 +05305176 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
5177 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005178 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
5179 out->flags);
5180 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07005181 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
5182 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5183 out->config = pcm_config_mmap_playback;
5184 out->stream.start = out_start;
5185 out->stream.stop = out_stop;
5186 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5187 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305188 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
5189 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Alexy Joseph98988832017-01-13 14:56:59 -08005190 out->dynamic_pm_qos_enabled = property_get_bool("vendor.audio.dynamic.qos.enable", false);
5191 if (!out->dynamic_pm_qos_enabled) {
5192 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
5193 } else {
5194 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
5195 //the mixer path will be a string similar to "low-latency-playback resume"
5196 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
5197 strlcat(out->pm_qos_mixer_path,
5198 " resume", MAX_MIXER_PATH_LEN);
5199 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
5200 out->pm_qos_mixer_path);
5201 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305202 out->config = pcm_config_low_latency;
5203 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
5204 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5205 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05305206 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
5207 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
5208 if (out->config.period_size <= 0) {
5209 ALOGE("Invalid configuration period size is not valid");
5210 ret = -EINVAL;
5211 goto error_open;
5212 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305213 } else {
5214 /* primary path is the default path selected if no other outputs are available/suitable */
5215 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
5216 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
5217 }
5218 out->hal_ip_format = format = out->format;
5219 out->config.format = hal_format_to_pcm(out->hal_ip_format);
5220 out->hal_op_format = pcm_format_to_hal(out->config.format);
5221 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
5222 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005223 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05305224 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305225 if (out->hal_ip_format != out->hal_op_format) {
5226 uint32_t buffer_size = out->config.period_size *
5227 format_to_bitwidth_table[out->hal_op_format] *
5228 out->config.channels;
5229 out->convert_buffer = calloc(1, buffer_size);
5230 if (out->convert_buffer == NULL){
5231 ALOGE("Allocation failed for convert buffer for size %d",
5232 out->compr_config.fragment_size);
5233 ret = -ENOMEM;
5234 goto error_open;
5235 }
5236 ALOGD("Convert buffer allocated of size %d", buffer_size);
5237 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005238 }
5239
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005240 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
5241 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305242
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005243 /* TODO remove this hardcoding and check why width is zero*/
5244 if (out->bit_width == 0)
5245 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305246 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005247 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05305248 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305249 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05305250 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08005251 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
5252 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
5253 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005254 if(adev->primary_output == NULL)
5255 adev->primary_output = out;
5256 else {
5257 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005258 ret = -EEXIST;
5259 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005260 }
5261 }
5262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005263 /* Check if this usecase is already existing */
5264 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07005265 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
5266 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005267 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005268 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005269 ret = -EEXIST;
5270 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005271 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005272
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005273 pthread_mutex_unlock(&adev->lock);
5274
5275 out->stream.common.get_sample_rate = out_get_sample_rate;
5276 out->stream.common.set_sample_rate = out_set_sample_rate;
5277 out->stream.common.get_buffer_size = out_get_buffer_size;
5278 out->stream.common.get_channels = out_get_channels;
5279 out->stream.common.get_format = out_get_format;
5280 out->stream.common.set_format = out_set_format;
5281 out->stream.common.standby = out_standby;
5282 out->stream.common.dump = out_dump;
5283 out->stream.common.set_parameters = out_set_parameters;
5284 out->stream.common.get_parameters = out_get_parameters;
5285 out->stream.common.add_audio_effect = out_add_audio_effect;
5286 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5287 out->stream.get_latency = out_get_latency;
5288 out->stream.set_volume = out_set_volume;
5289 out->stream.write = out_write;
5290 out->stream.get_render_position = out_get_render_position;
5291 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005292 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005293
Haynes Mathew George16081042017-05-31 17:16:49 -07005294 if (out->realtime)
5295 out->af_period_multiplier = af_period_multiplier;
5296 else
5297 out->af_period_multiplier = 1;
5298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005299 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005300 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005301 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005302
5303 config->format = out->stream.common.get_format(&out->stream.common);
5304 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5305 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5306
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305307 /*
5308 By locking output stream before registering, we allow the callback
5309 to update stream's state only after stream's initial state is set to
5310 adev state.
5311 */
5312 lock_output_stream(out);
5313 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5314 pthread_mutex_lock(&adev->lock);
5315 out->card_status = adev->card_status;
5316 pthread_mutex_unlock(&adev->lock);
5317 pthread_mutex_unlock(&out->lock);
5318
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005319 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305320 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07005321 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005322
5323 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
5324 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5325 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005326 /* setup a channel for client <--> adsp communication for stream events */
5327 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07005328 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
5329 (audio_extn_ip_hdlr_intf_supported(config->format))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005330 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
5331 out->usecase, PCM_PLAYBACK);
5332 hdlr_stream_cfg.flags = out->flags;
5333 hdlr_stream_cfg.type = PCM_PLAYBACK;
5334 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
5335 &hdlr_stream_cfg);
5336 if (ret) {
5337 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
5338 out->adsp_hdlr_stream_handle = NULL;
5339 }
5340 }
Naresh Tanniru85819452017-05-04 18:55:45 -07005341 if (audio_extn_ip_hdlr_intf_supported(config->format)) {
5342 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL);
5343 if (ret < 0) {
5344 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
5345 out->ip_hdlr_handle = NULL;
5346 }
5347 }
Eric Laurent994a6932013-07-17 11:51:42 -07005348 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005349 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005350
5351error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05305352 if (out->convert_buffer)
5353 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005354 free(out);
5355 *stream_out = NULL;
5356 ALOGD("%s: exit: ret %d", __func__, ret);
5357 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005358}
5359
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305360void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005361 struct audio_stream_out *stream)
5362{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005363 struct stream_out *out = (struct stream_out *)stream;
5364 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005365 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005366
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305367 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
5368
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305369 // must deregister from sndmonitor first to prevent races
5370 // between the callback and close_stream
5371 audio_extn_snd_mon_unregister_listener(out);
5372
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005373 /* close adsp hdrl session before standby */
5374 if (out->adsp_hdlr_stream_handle) {
5375 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
5376 if (ret)
5377 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
5378 out->adsp_hdlr_stream_handle = NULL;
5379 }
5380
Naresh Tanniru85819452017-05-04 18:55:45 -07005381 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
5382 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
5383 out->ip_hdlr_handle = NULL;
5384 }
5385
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005386 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305387 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005388 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305389 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305390 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005391 if(ret != 0)
5392 ALOGE("%s: Compress voip output cannot be closed, error:%d",
5393 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005394 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005395 out_standby(&stream->common);
5396
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005397 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005398 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005399 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005400 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005401 if (out->compr_config.codec != NULL)
5402 free(out->compr_config.codec);
5403 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005404
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305405 out->a2dp_compress_mute = false;
5406
Ashish Jain83a6cc22016-06-28 14:34:17 +05305407 if (out->convert_buffer != NULL) {
5408 free(out->convert_buffer);
5409 out->convert_buffer = NULL;
5410 }
5411
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005412 if (adev->voice_tx_output == out)
5413 adev->voice_tx_output = NULL;
5414
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05305415 if (adev->primary_output == out)
5416 adev->primary_output = NULL;
5417
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005418 pthread_cond_destroy(&out->cond);
5419 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005420 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005421 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005422}
5423
5424static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5425{
5426 struct audio_device *adev = (struct audio_device *)dev;
5427 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005428 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005429 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005430 int ret;
5431 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005432
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005433 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005434 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005435
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305436 if (!parms)
5437 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305438
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305439 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
5440 if (ret >= 0) {
5441 /* When set to false, HAL should disable EC and NS */
5442 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5443 adev->bt_sco_on = true;
5444 else
5445 adev->bt_sco_on = false;
5446 }
5447
Naresh Tanniru4c630392014-05-12 01:05:52 +05305448 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005449 status = voice_set_parameters(adev, parms);
5450 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005451 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005452
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005453 status = platform_set_parameters(adev->platform, parms);
5454 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005455 goto done;
5456
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005457 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5458 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07005459 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005460 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5461 adev->bluetooth_nrec = true;
5462 else
5463 adev->bluetooth_nrec = false;
5464 }
5465
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005466 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5467 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005468 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5469 adev->screen_off = false;
5470 else
5471 adev->screen_off = true;
5472 }
5473
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005474 ret = str_parms_get_int(parms, "rotation", &val);
5475 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005476 bool reverse_speakers = false;
5477 switch(val) {
5478 // FIXME: note that the code below assumes that the speakers are in the correct placement
5479 // relative to the user when the device is rotated 90deg from its default rotation. This
5480 // assumption is device-specific, not platform-specific like this code.
5481 case 270:
5482 reverse_speakers = true;
5483 break;
5484 case 0:
5485 case 90:
5486 case 180:
5487 break;
5488 default:
5489 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005490 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005491 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005492 if (status == 0) {
5493 if (adev->speaker_lr_swap != reverse_speakers) {
5494 adev->speaker_lr_swap = reverse_speakers;
5495 // only update the selected device if there is active pcm playback
5496 struct audio_usecase *usecase;
5497 struct listnode *node;
5498 list_for_each(node, &adev->usecase_list) {
5499 usecase = node_to_item(node, struct audio_usecase, list);
5500 if (usecase->type == PCM_PLAYBACK) {
5501 select_devices(adev, usecase->id);
5502 break;
5503 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005504 }
5505 }
5506 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005507 }
5508
Mingming Yin514a8bc2014-07-29 15:22:21 -07005509 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5510 if (ret >= 0) {
5511 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5512 adev->bt_wb_speech_enabled = true;
5513 else
5514 adev->bt_wb_speech_enabled = false;
5515 }
5516
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005517 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5518 if (ret >= 0) {
5519 val = atoi(value);
5520 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005521 ALOGV("cache new ext disp type and edid");
5522 ret = platform_get_ext_disp_type(adev->platform);
5523 if (ret < 0) {
5524 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08005525 status = ret;
5526 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005527 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005528 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005529 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005530 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07005531 /*
5532 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
5533 * Per AudioPolicyManager, USB device is higher priority than WFD.
5534 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
5535 * If WFD use case occupies AFE proxy, it may result unintended behavior while
5536 * starting voice call on USB
5537 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005538 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5539 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08005540 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5541 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005542 }
vivek mehta344576a2016-04-12 18:56:03 -07005543 ALOGV("detected USB connect .. disable proxy");
5544 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005545 }
5546 }
5547
5548 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5549 if (ret >= 0) {
5550 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07005551 /*
5552 * The HDMI / Displayport disconnect handling has been moved to
5553 * audio extension to ensure that its parameters are not
5554 * invalidated prior to updating sysfs of the disconnect event
5555 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
5556 */
5557 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005558 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005559 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5560 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05305561 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5562 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005563 }
vivek mehta344576a2016-04-12 18:56:03 -07005564 ALOGV("detected USB disconnect .. enable proxy");
5565 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005566 }
5567 }
5568
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305569 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
5570 if (ret >= 0) {
5571 struct audio_usecase *usecase;
5572 struct listnode *node;
5573 list_for_each(node, &adev->usecase_list) {
5574 usecase = node_to_item(node, struct audio_usecase, list);
5575 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07005576 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305577 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08005578
5579 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305580 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08005581 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305582 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305583 //force device switch to re configure encoder
5584 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305585 audio_extn_a2dp_set_handoff_mode(false);
5586 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305587 break;
5588 }
5589 }
5590 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005591
5592 //handle vr audio setparam
5593 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5594 value, sizeof(value));
5595 if (ret >= 0) {
5596 ALOGI("Setting vr mode to be %s", value);
5597 if (!strncmp(value, "true", 4)) {
5598 adev->vr_audio_mode_enabled = true;
5599 ALOGI("Setting vr mode to true");
5600 } else if (!strncmp(value, "false", 5)) {
5601 adev->vr_audio_mode_enabled = false;
5602 ALOGI("Setting vr mode to false");
5603 } else {
5604 ALOGI("wrong vr mode set");
5605 }
5606 }
5607
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305608 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005609done:
5610 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005611 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305612error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005613 ALOGV("%s: exit with code(%d)", __func__, status);
5614 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005615}
5616
5617static char* adev_get_parameters(const struct audio_hw_device *dev,
5618 const char *keys)
5619{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005620 struct audio_device *adev = (struct audio_device *)dev;
5621 struct str_parms *reply = str_parms_create();
5622 struct str_parms *query = str_parms_create_str(keys);
5623 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05305624 char value[256] = {0};
5625 int ret = 0;
5626
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005627 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005628 if (reply) {
5629 str_parms_destroy(reply);
5630 }
5631 if (query) {
5632 str_parms_destroy(query);
5633 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005634 ALOGE("adev_get_parameters: failed to create query or reply");
5635 return NULL;
5636 }
5637
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005638 //handle vr audio getparam
5639
5640 ret = str_parms_get_str(query,
5641 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5642 value, sizeof(value));
5643
5644 if (ret >= 0) {
5645 bool vr_audio_enabled = false;
5646 pthread_mutex_lock(&adev->lock);
5647 vr_audio_enabled = adev->vr_audio_mode_enabled;
5648 pthread_mutex_unlock(&adev->lock);
5649
5650 ALOGI("getting vr mode to %d", vr_audio_enabled);
5651
5652 if (vr_audio_enabled) {
5653 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5654 "true");
5655 goto exit;
5656 } else {
5657 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5658 "false");
5659 goto exit;
5660 }
5661 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005662
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005663 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005664 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08005665 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005666 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05305667 pthread_mutex_unlock(&adev->lock);
5668
Naresh Tannirud7205b62014-06-20 02:54:48 +05305669exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005670 str = str_parms_to_str(reply);
5671 str_parms_destroy(query);
5672 str_parms_destroy(reply);
5673
5674 ALOGV("%s: exit: returns - %s", __func__, str);
5675 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005676}
5677
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005678static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005679{
5680 return 0;
5681}
5682
5683static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5684{
Haynes Mathew George5191a852013-09-11 14:19:36 -07005685 int ret;
5686 struct audio_device *adev = (struct audio_device *)dev;
5687 pthread_mutex_lock(&adev->lock);
5688 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07005689 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005690 pthread_mutex_unlock(&adev->lock);
5691 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005692}
5693
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005694static int adev_set_master_volume(struct audio_hw_device *dev __unused,
5695 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005696{
5697 return -ENOSYS;
5698}
5699
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005700static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5701 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005702{
5703 return -ENOSYS;
5704}
5705
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005706static int adev_set_master_mute(struct audio_hw_device *dev __unused,
5707 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005708{
5709 return -ENOSYS;
5710}
5711
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005712static int adev_get_master_mute(struct audio_hw_device *dev __unused,
5713 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005714{
5715 return -ENOSYS;
5716}
5717
5718static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5719{
5720 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005721
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005722 pthread_mutex_lock(&adev->lock);
5723 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005724 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005725 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08005726 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005727 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07005728 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005729 adev->current_call_output = NULL;
5730 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005731 }
5732 pthread_mutex_unlock(&adev->lock);
5733 return 0;
5734}
5735
5736static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5737{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005738 int ret;
5739
5740 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08005741 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005742 ret = voice_set_mic_mute((struct audio_device *)dev, state);
5743 pthread_mutex_unlock(&adev->lock);
5744
5745 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005746}
5747
5748static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5749{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005750 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005751 return 0;
5752}
5753
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005754static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005755 const struct audio_config *config)
5756{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005757 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005758
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005759 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
5760 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005761}
5762
5763static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005764 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005765 audio_devices_t devices,
5766 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005767 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305768 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005769 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005770 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005771{
5772 struct audio_device *adev = (struct audio_device *)dev;
5773 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005774 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005775 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005776 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305777 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305778
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005779 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305780 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
5781 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005782 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305783 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005784
5785 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005786
5787 if (!in) {
5788 ALOGE("failed to allocate input stream");
5789 return -ENOMEM;
5790 }
5791
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305792 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305793 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
5794 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005795 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005796 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005797
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005798 in->stream.common.get_sample_rate = in_get_sample_rate;
5799 in->stream.common.set_sample_rate = in_set_sample_rate;
5800 in->stream.common.get_buffer_size = in_get_buffer_size;
5801 in->stream.common.get_channels = in_get_channels;
5802 in->stream.common.get_format = in_get_format;
5803 in->stream.common.set_format = in_set_format;
5804 in->stream.common.standby = in_standby;
5805 in->stream.common.dump = in_dump;
5806 in->stream.common.set_parameters = in_set_parameters;
5807 in->stream.common.get_parameters = in_get_parameters;
5808 in->stream.common.add_audio_effect = in_add_audio_effect;
5809 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5810 in->stream.set_gain = in_set_gain;
5811 in->stream.read = in_read;
5812 in->stream.get_input_frames_lost = in_get_input_frames_lost;
5813
5814 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005815 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005816 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005817 in->standby = 1;
5818 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005819 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005820 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005821
Dhananjay Kumar973fc362017-01-09 18:48:15 +05305822 in->usecase = USECASE_AUDIO_RECORD;
5823 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Haynes Mathew George16081042017-05-31 17:16:49 -07005824 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Dhananjay Kumar973fc362017-01-09 18:48:15 +05305825 is_low_latency = true;
5826#if LOW_LATENCY_CAPTURE_USE_CASE
5827 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
5828#endif
5829 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
5830 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005831 in->format = config->format;
Haynes Mathew George16081042017-05-31 17:16:49 -07005832 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5833 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
5834 in->realtime = 0;
5835 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5836 in->config = pcm_config_mmap_capture;
5837 in->stream.start = in_start;
5838 in->stream.stop = in_stop;
5839 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5840 in->stream.get_mmap_position = in_get_mmap_position;
5841 in->af_period_multiplier = 1;
5842 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
5843 } else if (in->realtime) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005844 in->config = pcm_config_audio_capture_rt;
5845 in->sample_rate = in->config.rate;
5846 in->af_period_multiplier = af_period_multiplier;
5847 } else {
5848 in->config = pcm_config_audio_capture;
5849 in->config.rate = config->sample_rate;
5850 in->sample_rate = config->sample_rate;
5851 in->af_period_multiplier = 1;
5852 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305853 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005854
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305855 /* restrict 24 bit capture for unprocessed source only
5856 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
5857 */
5858 if (config->format == AUDIO_FORMAT_DEFAULT) {
5859 config->format = AUDIO_FORMAT_PCM_16_BIT;
5860 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
5861 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
5862 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
5863 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5864 bool ret_error = false;
5865 in->bit_width = 24;
5866 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5867 from HAL is 24_packed and 8_24
5868 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5869 24_packed return error indicating supported format is 24_packed
5870 *> In case of any other source requesting 24 bit or float return error
5871 indicating format supported is 16 bit only.
5872
5873 on error flinger will retry with supported format passed
5874 */
5875 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
5876 (source != AUDIO_SOURCE_CAMCORDER)) {
5877 config->format = AUDIO_FORMAT_PCM_16_BIT;
5878 if (config->sample_rate > 48000)
5879 config->sample_rate = 48000;
5880 ret_error = true;
5881 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
5882 in->config.format = PCM_FORMAT_S24_3LE;
5883 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5884 in->config.format = PCM_FORMAT_S24_LE;
5885 } else {
5886 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
5887 ret_error = true;
5888 }
5889
5890 if (ret_error) {
5891 ret = -EINVAL;
5892 goto err_open;
5893 }
5894 }
5895
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305896 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305897 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
5898 (adev->mode != AUDIO_MODE_IN_CALL)) {
5899 ret = -EINVAL;
5900 goto err_open;
5901 }
5902
5903 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
5904 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005905 if (config->sample_rate == 0)
5906 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5907 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5908 config->sample_rate != 8000) {
5909 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5910 ret = -EINVAL;
5911 goto err_open;
5912 }
5913 if (config->format == AUDIO_FORMAT_DEFAULT)
5914 config->format = AUDIO_FORMAT_PCM_16_BIT;
5915 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5916 config->format = AUDIO_FORMAT_PCM_16_BIT;
5917 ret = -EINVAL;
5918 goto err_open;
5919 }
5920
5921 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5922 in->config = pcm_config_afe_proxy_record;
5923 in->config.channels = channel_count;
5924 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305925 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305926 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
5927 in, config, &channel_mask_updated)) {
5928 if (channel_mask_updated == true) {
5929 ALOGD("%s: return error to retry with updated channel mask (%#x)",
5930 __func__, config->channel_mask);
5931 ret = -EINVAL;
5932 goto err_open;
5933 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05305934 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07005935 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005936 audio_extn_compr_cap_format_supported(config->format) &&
5937 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005938 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305939 } else if (audio_extn_cin_applicable_stream(in)) {
5940 ret = audio_extn_cin_configure_input_stream(in);
5941 if (ret)
5942 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005943 } else {
5944 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005945 if (!in->realtime) {
5946 in->format = config->format;
5947 frame_size = audio_stream_in_frame_size(&in->stream);
5948 buffer_size = get_input_buffer_size(config->sample_rate,
5949 config->format,
5950 channel_count,
5951 is_low_latency);
5952 in->config.period_size = buffer_size / frame_size;
5953 }
5954
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005955#ifndef COMPRESS_VOIP_ENABLED
5956 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5957 (in->config.rate == 8000 || in->config.rate == 16000 ||
5958 in->config.rate == 32000 || in->config.rate == 48000) &&
5959 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5960
5961 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5962 in->config = default_pcm_config_voip_copp;
5963 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5964 in->config.rate = in->sample_rate;
5965#else
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005966 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
Haynes Mathew George16081042017-05-31 17:16:49 -07005967 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
5968 voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005969 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005970 (in->config.rate == 8000 || in->config.rate == 16000 ||
5971 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005972 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5973 voice_extn_compress_voip_open_input_stream(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005974#endif
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005975 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005976 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005977
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305978 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5979 &adev->streams_input_cfg_list,
5980 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305981 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305982
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005983 /* This stream could be for sound trigger lab,
5984 get sound trigger pcm if present */
5985 audio_extn_sound_trigger_check_and_get_session(in);
5986
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305987 lock_input_stream(in);
5988 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5989 pthread_mutex_lock(&adev->lock);
5990 in->card_status = adev->card_status;
5991 pthread_mutex_unlock(&adev->lock);
5992 pthread_mutex_unlock(&in->lock);
5993
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005994 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005995 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005996 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005997
5998err_open:
5999 free(in);
6000 *stream_in = NULL;
6001 return ret;
6002}
6003
6004static void adev_close_input_stream(struct audio_hw_device *dev,
6005 struct audio_stream_in *stream)
6006{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006007 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006008 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006009 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306010
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306011 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006012
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306013 // must deregister from sndmonitor first to prevent races
6014 // between the callback and close_stream
6015 audio_extn_snd_mon_unregister_listener(stream);
6016
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306017 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07006018 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306019
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006020 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306021 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006022 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306023 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006024 if (ret != 0)
6025 ALOGE("%s: Compress voip input cannot be closed, error:%d",
6026 __func__, ret);
6027 } else
6028 in_standby(&stream->common);
6029
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07006030 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006031 audio_extn_ssr_deinit();
6032 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006033
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306034 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07006035 audio_extn_compr_cap_format_supported(in->config.format))
6036 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306037
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306038 if (audio_extn_cin_attached_usecase(in->usecase))
6039 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006040
Mingming Yinfd7607b2016-01-22 12:48:44 -08006041 if (in->is_st_session) {
6042 ALOGV("%s: sound trigger pcm stop lab", __func__);
6043 audio_extn_sound_trigger_stop_lab(in);
6044 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006045 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006046 return;
6047}
6048
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306049int adev_create_audio_patch(struct audio_hw_device *dev,
6050 unsigned int num_sources,
6051 const struct audio_port_config *sources,
6052 unsigned int num_sinks,
6053 const struct audio_port_config *sinks,
6054 audio_patch_handle_t *handle)
6055{
6056
6057
6058 return audio_extn_hw_loopback_create_audio_patch(dev,
6059 num_sources,
6060 sources,
6061 num_sinks,
6062 sinks,
6063 handle);
6064
6065}
6066
6067int adev_release_audio_patch(struct audio_hw_device *dev,
6068 audio_patch_handle_t handle)
6069{
6070 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
6071}
6072
6073int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
6074{
6075 return audio_extn_hw_loopback_get_audio_port(dev, config);
6076}
6077
6078int adev_set_audio_port_config(struct audio_hw_device *dev,
6079 const struct audio_port_config *config)
6080{
6081 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
6082}
6083
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006084static int adev_dump(const audio_hw_device_t *device __unused,
6085 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006086{
6087 return 0;
6088}
6089
6090static int adev_close(hw_device_t *device)
6091{
6092 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07006093
6094 if (!adev)
6095 return 0;
6096
6097 pthread_mutex_lock(&adev_init_lock);
6098
6099 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306100 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006101 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08006102 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306103 audio_extn_utils_release_streams_cfg_lists(
6104 &adev->streams_output_cfg_list,
6105 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306106 if (audio_extn_qaf_is_enabled())
6107 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006108 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006109 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006110 free(adev->snd_dev_ref_cnt);
6111 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006112 if (adev->adm_deinit)
6113 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306114 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006115 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306116 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306117 audio_extn_hw_loopback_deinit(adev);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306118 if (adev->device_cfg_params) {
6119 free(adev->device_cfg_params);
6120 adev->device_cfg_params = NULL;
6121 }
Kiran Kandi910e1862013-10-29 13:29:42 -07006122 free(device);
6123 adev = NULL;
6124 }
6125 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006126
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006127 return 0;
6128}
6129
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006130/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6131 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6132 * just that it _might_ work.
6133 */
6134static int period_size_is_plausible_for_low_latency(int period_size)
6135{
6136 switch (period_size) {
6137 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07006138 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006139 case 240:
6140 case 320:
6141 case 480:
6142 return 1;
6143 default:
6144 return 0;
6145 }
6146}
6147
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306148static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
6149{
6150 bool is_snd_card_status = false;
6151 bool is_ext_device_status = false;
6152 char value[32];
6153 int card = -1;
6154 card_status_t status;
6155
6156 if (cookie != adev || !parms)
6157 return;
6158
6159 if (!parse_snd_card_status(parms, &card, &status)) {
6160 is_snd_card_status = true;
6161 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
6162 is_ext_device_status = true;
6163 } else {
6164 // not a valid event
6165 return;
6166 }
6167
6168 pthread_mutex_lock(&adev->lock);
6169 if (card == adev->snd_card || is_ext_device_status) {
6170 if (is_snd_card_status && adev->card_status != status) {
6171 adev->card_status = status;
6172 platform_snd_card_update(adev->platform, status);
6173 audio_extn_fm_set_parameters(adev, parms);
6174 } else if (is_ext_device_status) {
6175 platform_set_parameters(adev->platform, parms);
6176 }
6177 }
6178 pthread_mutex_unlock(&adev->lock);
6179 return;
6180}
6181
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306182/* out and adev lock held */
6183static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6184{
6185 struct audio_usecase *uc_info;
6186 float left_p;
6187 float right_p;
6188 audio_devices_t devices;
6189
6190 uc_info = get_usecase_from_list(adev, out->usecase);
6191 if (uc_info == NULL) {
6192 ALOGE("%s: Could not find the usecase (%d) in the list",
6193 __func__, out->usecase);
6194 return -EINVAL;
6195 }
6196
6197 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6198 out->usecase, use_case_table[out->usecase]);
6199
6200 if (restore) {
6201 // restore A2DP device for active usecases and unmute if required
6202 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6203 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
6204 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
6205 select_devices(adev, uc_info->id);
6206 pthread_mutex_lock(&out->compr_mute_lock);
6207 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6208 (out->a2dp_compress_mute)) {
6209 out->a2dp_compress_mute = false;
6210 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6211 }
6212 pthread_mutex_unlock(&out->compr_mute_lock);
6213 }
6214 } else {
6215 // mute compress stream if suspended
6216 pthread_mutex_lock(&out->compr_mute_lock);
6217 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6218 (!out->a2dp_compress_mute)) {
6219 if (!out->standby) {
6220 ALOGD("%s: selecting speaker and muting stream", __func__);
6221 devices = out->devices;
6222 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6223 left_p = out->volume_l;
6224 right_p = out->volume_r;
6225 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6226 compress_pause(out->compr);
6227 out_set_compr_volume(&out->stream, (float)0, (float)0);
6228 out->a2dp_compress_mute = true;
6229 select_devices(adev, out->usecase);
6230 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6231 compress_resume(out->compr);
6232 out->devices = devices;
6233 out->volume_l = left_p;
6234 out->volume_r = right_p;
6235 }
6236 }
6237 pthread_mutex_unlock(&out->compr_mute_lock);
6238 }
6239 ALOGV("%s: exit", __func__);
6240 return 0;
6241}
6242
6243int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6244{
6245 int ret = 0;
6246
6247 lock_output_stream(out);
6248 pthread_mutex_lock(&adev->lock);
6249
6250 ret = check_a2dp_restore_l(adev, out, restore);
6251
6252 pthread_mutex_unlock(&adev->lock);
6253 pthread_mutex_unlock(&out->lock);
6254 return ret;
6255}
6256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006257static int adev_open(const hw_module_t *module, const char *name,
6258 hw_device_t **device)
6259{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306260 int ret;
6261
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006262 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006263 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
6264
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006265 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07006266 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006267 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07006268 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006269 ALOGD("%s: returning existing instance of adev", __func__);
6270 ALOGD("%s: exit", __func__);
6271 pthread_mutex_unlock(&adev_init_lock);
6272 return 0;
6273 }
6274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006275 adev = calloc(1, sizeof(struct audio_device));
6276
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006277 if (!adev) {
6278 pthread_mutex_unlock(&adev_init_lock);
6279 return -ENOMEM;
6280 }
6281
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006282 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6283
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05306284#ifdef DYNAMIC_LOG_ENABLED
6285 register_for_dynamic_logging("hal");
6286#endif
6287
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006288 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6289 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6290 adev->device.common.module = (struct hw_module_t *)module;
6291 adev->device.common.close = adev_close;
6292
6293 adev->device.init_check = adev_init_check;
6294 adev->device.set_voice_volume = adev_set_voice_volume;
6295 adev->device.set_master_volume = adev_set_master_volume;
6296 adev->device.get_master_volume = adev_get_master_volume;
6297 adev->device.set_master_mute = adev_set_master_mute;
6298 adev->device.get_master_mute = adev_get_master_mute;
6299 adev->device.set_mode = adev_set_mode;
6300 adev->device.set_mic_mute = adev_set_mic_mute;
6301 adev->device.get_mic_mute = adev_get_mic_mute;
6302 adev->device.set_parameters = adev_set_parameters;
6303 adev->device.get_parameters = adev_get_parameters;
6304 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6305 adev->device.open_output_stream = adev_open_output_stream;
6306 adev->device.close_output_stream = adev_close_output_stream;
6307 adev->device.open_input_stream = adev_open_input_stream;
6308 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306309 adev->device.create_audio_patch = adev_create_audio_patch;
6310 adev->device.release_audio_patch = adev_release_audio_patch;
6311 adev->device.get_audio_port = adev_get_audio_port;
6312 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006313 adev->device.dump = adev_dump;
6314
6315 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006316 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08006317 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006318 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006319 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006320 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006321 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07006322 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306323 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006324 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006325 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006326 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006327 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08006328 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006329 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05306330 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306331 adev->perf_lock_opts[0] = 0x101;
6332 adev->perf_lock_opts[1] = 0x20E;
6333 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306334
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006335 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006336 adev->platform = platform_init(adev);
6337 if (!adev->platform) {
6338 free(adev->snd_dev_ref_cnt);
6339 free(adev);
6340 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6341 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08006342 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306343 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006344 return -EINVAL;
6345 }
Eric Laurentc4aef752013-09-12 17:45:53 -07006346
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306347 if (audio_extn_qaf_is_enabled()) {
6348 ret = audio_extn_qaf_init(adev);
6349 if (ret < 0) {
6350 free(adev);
6351 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6352 *device = NULL;
6353 pthread_mutex_unlock(&adev_init_lock);
6354 pthread_mutex_destroy(&adev->lock);
6355 return ret;
6356 }
6357
6358 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
6359 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
6360 }
6361
Eric Laurentc4aef752013-09-12 17:45:53 -07006362 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
6363 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6364 if (adev->visualizer_lib == NULL) {
6365 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6366 } else {
6367 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6368 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006369 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006370 "visualizer_hal_start_output");
6371 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006372 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006373 "visualizer_hal_stop_output");
6374 }
6375 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05306376 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08006377 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006378 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306379 audio_extn_hw_loopback_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07006380
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006381 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
6382 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6383 if (adev->offload_effects_lib == NULL) {
6384 ALOGE("%s: DLOPEN failed for %s", __func__,
6385 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6386 } else {
6387 ALOGV("%s: DLOPEN successful for %s", __func__,
6388 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6389 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05306390 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006391 "offload_effects_bundle_hal_start_output");
6392 adev->offload_effects_stop_output =
6393 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6394 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006395 adev->offload_effects_set_hpx_state =
6396 (int (*)(bool))dlsym(adev->offload_effects_lib,
6397 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05306398 adev->offload_effects_get_parameters =
6399 (void (*)(struct str_parms *, struct str_parms *))
6400 dlsym(adev->offload_effects_lib,
6401 "offload_effects_bundle_get_parameters");
6402 adev->offload_effects_set_parameters =
6403 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
6404 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006405 }
6406 }
6407
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006408 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
6409 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6410 if (adev->adm_lib == NULL) {
6411 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6412 } else {
6413 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6414 adev->adm_init = (adm_init_t)
6415 dlsym(adev->adm_lib, "adm_init");
6416 adev->adm_deinit = (adm_deinit_t)
6417 dlsym(adev->adm_lib, "adm_deinit");
6418 adev->adm_register_input_stream = (adm_register_input_stream_t)
6419 dlsym(adev->adm_lib, "adm_register_input_stream");
6420 adev->adm_register_output_stream = (adm_register_output_stream_t)
6421 dlsym(adev->adm_lib, "adm_register_output_stream");
6422 adev->adm_deregister_stream = (adm_deregister_stream_t)
6423 dlsym(adev->adm_lib, "adm_deregister_stream");
6424 adev->adm_request_focus = (adm_request_focus_t)
6425 dlsym(adev->adm_lib, "adm_request_focus");
6426 adev->adm_abandon_focus = (adm_abandon_focus_t)
6427 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006428 adev->adm_set_config = (adm_set_config_t)
6429 dlsym(adev->adm_lib, "adm_set_config");
6430 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6431 dlsym(adev->adm_lib, "adm_request_focus_v2");
6432 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6433 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6434 adev->adm_on_routing_change = (adm_on_routing_change_t)
6435 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006436 }
6437 }
6438
Mingming Yin514a8bc2014-07-29 15:22:21 -07006439 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006440 //initialize this to false for now,
6441 //this will be set to true through set param
6442 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07006443
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07006444 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006445 *device = &adev->device.common;
6446
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306447 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
6448 &adev->streams_output_cfg_list,
6449 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006450
Kiran Kandi910e1862013-10-29 13:29:42 -07006451 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006452
6453 char value[PROPERTY_VALUE_MAX];
6454 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006455 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006456 trial = atoi(value);
6457 if (period_size_is_plausible_for_low_latency(trial)) {
6458 pcm_config_low_latency.period_size = trial;
6459 pcm_config_low_latency.start_threshold = trial / 4;
6460 pcm_config_low_latency.avail_min = trial / 4;
6461 configured_low_latency_capture_period_size = trial;
6462 }
6463 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006464 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006465 trial = atoi(value);
6466 if (period_size_is_plausible_for_low_latency(trial)) {
6467 configured_low_latency_capture_period_size = trial;
6468 }
6469 }
6470
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006471 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006472 af_period_multiplier = atoi(value);
6473 if (af_period_multiplier < 0)
6474 af_period_multiplier = 2;
6475 else if (af_period_multiplier > 4)
6476 af_period_multiplier = 4;
6477
6478 ALOGV("new period_multiplier = %d", af_period_multiplier);
6479 }
6480
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006481 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006482 pthread_mutex_unlock(&adev_init_lock);
6483
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006484 if (adev->adm_init)
6485 adev->adm_data = adev->adm_init();
6486
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306487 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306488 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006489 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306490
6491 audio_extn_snd_mon_init();
6492 pthread_mutex_lock(&adev->lock);
6493 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
6494 adev->card_status = CARD_STATUS_ONLINE;
6495 pthread_mutex_unlock(&adev->lock);
6496 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306497 /* Allocate memory for Device config params */
6498 adev->device_cfg_params = (struct audio_device_config_param*)
6499 calloc(platform_get_max_codec_backend(),
6500 sizeof(struct audio_device_config_param));
6501 if (adev->device_cfg_params == NULL)
6502 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306503
Eric Laurent994a6932013-07-17 11:51:42 -07006504 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006505 return 0;
6506}
6507
6508static struct hw_module_methods_t hal_module_methods = {
6509 .open = adev_open,
6510};
6511
6512struct audio_module HAL_MODULE_INFO_SYM = {
6513 .common = {
6514 .tag = HARDWARE_MODULE_TAG,
6515 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6516 .hal_api_version = HARDWARE_HAL_API_VERSION,
6517 .id = AUDIO_HARDWARE_MODULE_ID,
6518 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08006519 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006520 .methods = &hal_module_methods,
6521 },
6522};