blob: 9d14ec3b35c24284f74cae5007dafe3cec9362ed [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>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053079#ifdef DYNAMIC_LOG_ENABLED
80#include <log_xml_parser.h>
81#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
82#include <log_utils.h>
83#endif
84
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070085#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053086/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
87#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070089#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053090#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070092#define PROXY_OPEN_RETRY_COUNT 100
93#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080094
Mingming Yin08c7e312015-03-16 18:10:58 -070095#ifdef USE_LL_AS_PRIMARY_OUTPUT
96#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
97#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
98#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080099#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700100#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
101#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800102
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700103#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700104#define DEFAULT_VOIP_BUF_DURATION_MS 20
105#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
106#define DEFAULT_VOIP_SAMP_RATE 48000
107
108#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
109
110struct pcm_config default_pcm_config_voip_copp = {
111 .channels = 1,
112 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
113 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
114 .period_count = 2,
115 .format = PCM_FORMAT_S16_LE,
116};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700117
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700118static unsigned int configured_low_latency_capture_period_size =
119 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
120
Eric Laurentb23d5282013-05-14 15:27:20 -0700121struct pcm_config pcm_config_deep_buffer = {
122 .channels = 2,
123 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
124 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
125 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
126 .format = PCM_FORMAT_S16_LE,
127 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
128 .stop_threshold = INT_MAX,
129 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
130};
131
132struct pcm_config pcm_config_low_latency = {
133 .channels = 2,
134 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
135 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
136 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
137 .format = PCM_FORMAT_S16_LE,
138 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
139 .stop_threshold = INT_MAX,
140 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
141};
142
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700143static int af_period_multiplier = 4;
144struct pcm_config pcm_config_rt = {
145 .channels = 2,
146 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
147 .period_size = ULL_PERIOD_SIZE, //1 ms
148 .period_count = 512, //=> buffer size is 512ms
149 .format = PCM_FORMAT_S16_LE,
150 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
151 .stop_threshold = INT_MAX,
152 .silence_threshold = 0,
153 .silence_size = 0,
154 .avail_min = ULL_PERIOD_SIZE, //1 ms
155};
156
Eric Laurentb23d5282013-05-14 15:27:20 -0700157struct pcm_config pcm_config_hdmi_multi = {
158 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
159 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
160 .period_size = HDMI_MULTI_PERIOD_SIZE,
161 .period_count = HDMI_MULTI_PERIOD_COUNT,
162 .format = PCM_FORMAT_S16_LE,
163 .start_threshold = 0,
164 .stop_threshold = INT_MAX,
165 .avail_min = 0,
166};
167
168struct pcm_config pcm_config_audio_capture = {
169 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700170 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
171 .format = PCM_FORMAT_S16_LE,
172};
173
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700174struct pcm_config pcm_config_audio_capture_rt = {
175 .channels = 2,
176 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
177 .period_size = ULL_PERIOD_SIZE,
178 .period_count = 512,
179 .format = PCM_FORMAT_S16_LE,
180 .start_threshold = 0,
181 .stop_threshold = INT_MAX,
182 .silence_threshold = 0,
183 .silence_size = 0,
184 .avail_min = ULL_PERIOD_SIZE, //1 ms
185};
186
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700187#define AFE_PROXY_CHANNEL_COUNT 2
188#define AFE_PROXY_SAMPLING_RATE 48000
189
190#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
191#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
192
193struct pcm_config pcm_config_afe_proxy_playback = {
194 .channels = AFE_PROXY_CHANNEL_COUNT,
195 .rate = AFE_PROXY_SAMPLING_RATE,
196 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
197 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
198 .format = PCM_FORMAT_S16_LE,
199 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
200 .stop_threshold = INT_MAX,
201 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
202};
203
204#define AFE_PROXY_RECORD_PERIOD_SIZE 768
205#define AFE_PROXY_RECORD_PERIOD_COUNT 4
206
207struct pcm_config pcm_config_afe_proxy_record = {
208 .channels = AFE_PROXY_CHANNEL_COUNT,
209 .rate = AFE_PROXY_SAMPLING_RATE,
210 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
211 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
212 .format = PCM_FORMAT_S16_LE,
213 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
214 .stop_threshold = INT_MAX,
215 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
216};
217
Ashish Jainf1eaa582016-05-23 20:54:24 +0530218#define AUDIO_MAX_PCM_FORMATS 7
219
220const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
221 [AUDIO_FORMAT_DEFAULT] = 0,
222 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
223 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
224 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
225 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
226 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
227 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
228};
229
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800230const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700231 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
232 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700233 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
234 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700235 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700236 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700237 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
238 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
239 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
240 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
241 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
242 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
243 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
244 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700245
Eric Laurentb23d5282013-05-14 15:27:20 -0700246 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700247 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530248 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
249 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
250 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700251 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700252 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700253 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800254 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800255 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700256 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700257
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700258 [USECASE_VOICE2_CALL] = "voice2-call",
259 [USECASE_VOLTE_CALL] = "volte-call",
260 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800261 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800262 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
263 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800264 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700265 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
266 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
267 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800268 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
269 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
270 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
271
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700272 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
273 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700274 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
275 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700276
277 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
278 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700279 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700280
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530281 /* Transcode loopback cases */
282 [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700283
284 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
285 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Eric Laurentb23d5282013-05-14 15:27:20 -0700286};
287
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700288static const audio_usecase_t offload_usecases[] = {
289 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700290 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
291 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
292 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
293 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
294 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
295 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
296 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
297 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700298};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800299
300#define STRING_TO_ENUM(string) { #string, string }
301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800302struct string_to_enum {
303 const char *name;
304 uint32_t value;
305};
306
307static const struct string_to_enum out_channels_name_to_enum_table[] = {
308 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800309 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
310 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
311 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700312 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800313 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
314 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800315 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
316};
317
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700318static const struct string_to_enum out_formats_name_to_enum_table[] = {
319 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
320 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
321 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700322 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800323 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
324 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700325 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800326};
327
328//list of all supported sample rates by HDMI specification.
329static const int out_hdmi_sample_rates[] = {
330 32000, 44100, 48000, 88200, 96000, 176400, 192000,
331};
332
333static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
334 STRING_TO_ENUM(32000),
335 STRING_TO_ENUM(44100),
336 STRING_TO_ENUM(48000),
337 STRING_TO_ENUM(88200),
338 STRING_TO_ENUM(96000),
339 STRING_TO_ENUM(176400),
340 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700341};
342
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700343static struct audio_device *adev = NULL;
344static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700345static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700346//cache last MBDRC cal step level
347static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700348
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530349static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
350static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
351
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700352static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
353 int flags __unused)
354{
355 int dir = 0;
356 switch (uc_id) {
357 case USECASE_AUDIO_RECORD_LOW_LATENCY:
358 dir = 1;
359 case USECASE_AUDIO_PLAYBACK_ULL:
360 break;
361 default:
362 return false;
363 }
364
365 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
366 PCM_PLAYBACK : PCM_CAPTURE);
367 if (adev->adm_is_noirq_avail)
368 return adev->adm_is_noirq_avail(adev->adm_data,
369 adev->snd_card, dev_id, dir);
370 return false;
371}
372
373static void register_out_stream(struct stream_out *out)
374{
375 struct audio_device *adev = out->dev;
376 if (is_offload_usecase(out->usecase) ||
377 !adev->adm_register_output_stream)
378 return;
379
380 // register stream first for backward compatibility
381 adev->adm_register_output_stream(adev->adm_data,
382 out->handle,
383 out->flags);
384
385 if (!adev->adm_set_config)
386 return;
387
388 if (out->realtime)
389 adev->adm_set_config(adev->adm_data,
390 out->handle,
391 out->pcm, &out->config);
392}
393
394static void register_in_stream(struct stream_in *in)
395{
396 struct audio_device *adev = in->dev;
397 if (!adev->adm_register_input_stream)
398 return;
399
400 adev->adm_register_input_stream(adev->adm_data,
401 in->capture_handle,
402 in->flags);
403
404 if (!adev->adm_set_config)
405 return;
406
407 if (in->realtime)
408 adev->adm_set_config(adev->adm_data,
409 in->capture_handle,
410 in->pcm,
411 &in->config);
412}
413
414static void request_out_focus(struct stream_out *out, long ns)
415{
416 struct audio_device *adev = out->dev;
417
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700418 if (adev->adm_request_focus_v2)
419 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
420 else if (adev->adm_request_focus)
421 adev->adm_request_focus(adev->adm_data, out->handle);
422}
423
424static void request_in_focus(struct stream_in *in, long ns)
425{
426 struct audio_device *adev = in->dev;
427
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700428 if (adev->adm_request_focus_v2)
429 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
430 else if (adev->adm_request_focus)
431 adev->adm_request_focus(adev->adm_data, in->capture_handle);
432}
433
434static void release_out_focus(struct stream_out *out)
435{
436 struct audio_device *adev = out->dev;
437
438 if (adev->adm_abandon_focus)
439 adev->adm_abandon_focus(adev->adm_data, out->handle);
440}
441
442static void release_in_focus(struct stream_in *in)
443{
444 struct audio_device *adev = in->dev;
445 if (adev->adm_abandon_focus)
446 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
447}
448
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530449static int parse_snd_card_status(struct str_parms *parms, int *card,
450 card_status_t *status)
451{
452 char value[32]={0};
453 char state[32]={0};
454
455 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
456 if (ret < 0)
457 return -1;
458
459 // sscanf should be okay as value is of max length 32.
460 // same as sizeof state.
461 if (sscanf(value, "%d,%s", card, state) < 2)
462 return -1;
463
464 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
465 CARD_STATUS_OFFLINE;
466 return 0;
467}
468
vivek mehtaa76401a2015-04-24 14:12:15 -0700469__attribute__ ((visibility ("default")))
470bool audio_hw_send_gain_dep_calibration(int level) {
471 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700472 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700473
474 pthread_mutex_lock(&adev_init_lock);
475
476 if (adev != NULL && adev->platform != NULL) {
477 pthread_mutex_lock(&adev->lock);
478 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700479
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530480 // cache level info for any of the use case which
481 // was not started.
482 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700483
vivek mehtaa76401a2015-04-24 14:12:15 -0700484 pthread_mutex_unlock(&adev->lock);
485 } else {
486 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
487 }
488
489 pthread_mutex_unlock(&adev_init_lock);
490
491 return ret_val;
492}
493
Ashish Jain5106d362016-05-11 19:23:33 +0530494static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
495{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800496 bool gapless_enabled = false;
497 const char *mixer_ctl_name = "Compress Gapless Playback";
498 struct mixer_ctl *ctl;
499
500 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700501 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530502
503 /*Disable gapless if its AV playback*/
504 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800505
506 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
507 if (!ctl) {
508 ALOGE("%s: Could not get ctl for mixer cmd - %s",
509 __func__, mixer_ctl_name);
510 return -EINVAL;
511 }
512
513 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
514 ALOGE("%s: Could not set gapless mode %d",
515 __func__, gapless_enabled);
516 return -EINVAL;
517 }
518 return 0;
519}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700520
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700521__attribute__ ((visibility ("default")))
522int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
523 int table_size) {
524 int ret_val = 0;
525 ALOGV("%s: enter ... ", __func__);
526
527 pthread_mutex_lock(&adev_init_lock);
528 if (adev == NULL) {
529 ALOGW("%s: adev is NULL .... ", __func__);
530 goto done;
531 }
532
533 pthread_mutex_lock(&adev->lock);
534 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
535 pthread_mutex_unlock(&adev->lock);
536done:
537 pthread_mutex_unlock(&adev_init_lock);
538 ALOGV("%s: exit ... ", __func__);
539 return ret_val;
540}
541
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700542static bool is_supported_format(audio_format_t format)
543{
Eric Laurent86e17132013-09-12 17:49:30 -0700544 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530545 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530546 format == AUDIO_FORMAT_AAC_LC ||
547 format == AUDIO_FORMAT_AAC_HE_V1 ||
548 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530549 format == AUDIO_FORMAT_AAC_ADTS_LC ||
550 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
551 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530552 format == AUDIO_FORMAT_AAC_LATM_LC ||
553 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
554 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530555 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
556 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530557 format == AUDIO_FORMAT_PCM_FLOAT ||
558 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700559 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530560 format == AUDIO_FORMAT_AC3 ||
561 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700562 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530563 format == AUDIO_FORMAT_DTS ||
564 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800565 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530566 format == AUDIO_FORMAT_ALAC ||
567 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530568 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530569 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800570 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530571 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700572 format == AUDIO_FORMAT_APTX ||
573 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800574 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700575
576 return false;
577}
578
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700579static inline bool is_mmap_usecase(audio_usecase_t uc_id)
580{
581 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
582 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
583}
584
Avinash Vaish71a8b972014-07-24 15:36:33 +0530585static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
586 struct audio_usecase *uc_info)
587{
588 struct listnode *node;
589 struct audio_usecase *usecase;
590
591 if (uc_info == NULL)
592 return -EINVAL;
593
594 /* Re-route all voice usecases on the shared backend other than the
595 specified usecase to new snd devices */
596 list_for_each(node, &adev->usecase_list) {
597 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800598 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530599 enable_audio_route(adev, usecase);
600 }
601 return 0;
602}
603
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530604static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530605{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530606 ALOGV("%s", __func__);
607 audio_route_apply_and_update_path(adev->audio_route,
608 "asrc-mode");
609 adev->asrc_mode_enabled = true;
610}
611
612static void disable_asrc_mode(struct audio_device *adev)
613{
614 ALOGV("%s", __func__);
615 audio_route_reset_and_update_path(adev->audio_route,
616 "asrc-mode");
617 adev->asrc_mode_enabled = false;
618}
619
620/*
621 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
622 * 44.1 or Native DSD backends are enabled for any of current use case.
623 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
624 * - Disable current mix path use case(Headphone backend) and re-enable it with
625 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
626 * e.g. Naitve DSD or Headphone 44.1 -> + 48
627 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530628static void check_and_set_asrc_mode(struct audio_device *adev,
629 struct audio_usecase *uc_info,
630 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530631{
632 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530633 int i, num_new_devices = 0;
634 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
635 /*
636 *Split snd device for new combo use case
637 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
638 */
639 if (platform_split_snd_device(adev->platform,
640 snd_device,
641 &num_new_devices,
642 split_new_snd_devices) == 0) {
643 for (i = 0; i < num_new_devices; i++)
644 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
645 } else {
646 int new_backend_idx = platform_get_backend_index(snd_device);
647 if (((new_backend_idx == HEADPHONE_BACKEND) ||
648 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
649 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
650 !adev->asrc_mode_enabled) {
651 struct listnode *node = NULL;
652 struct audio_usecase *uc = NULL;
653 struct stream_out *curr_out = NULL;
654 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
655 int i, num_devices, ret = 0;
656 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530657
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530658 list_for_each(node, &adev->usecase_list) {
659 uc = node_to_item(node, struct audio_usecase, list);
660 curr_out = (struct stream_out*) uc->stream.out;
661 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
662 /*
663 *Split snd device for existing combo use case
664 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
665 */
666 ret = platform_split_snd_device(adev->platform,
667 uc->out_snd_device,
668 &num_devices,
669 split_snd_devices);
670 if (ret < 0 || num_devices == 0) {
671 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
672 split_snd_devices[0] = uc->out_snd_device;
673 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800674 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530675 for (i = 0; i < num_devices; i++) {
676 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
677 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
678 if((new_backend_idx == HEADPHONE_BACKEND) &&
679 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
680 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
681 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
682 __func__);
683 enable_asrc_mode(adev);
684 break;
685 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
686 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
687 (usecase_backend_idx == HEADPHONE_BACKEND)) {
688 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
689 __func__);
690 disable_audio_route(adev, uc);
691 disable_snd_device(adev, uc->out_snd_device);
692 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
693 if (new_backend_idx == DSD_NATIVE_BACKEND)
694 audio_route_apply_and_update_path(adev->audio_route,
695 "hph-true-highquality-mode");
696 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
697 (curr_out->bit_width >= 24))
698 audio_route_apply_and_update_path(adev->audio_route,
699 "hph-highquality-mode");
700 enable_asrc_mode(adev);
701 enable_snd_device(adev, uc->out_snd_device);
702 enable_audio_route(adev, uc);
703 break;
704 }
705 }
706 // reset split devices count
707 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800708 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530709 if (adev->asrc_mode_enabled)
710 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530711 }
712 }
713 }
714}
715
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700716int pcm_ioctl(struct pcm *pcm, int request, ...)
717{
718 va_list ap;
719 void * arg;
720 int pcm_fd = *(int*)pcm;
721
722 va_start(ap, request);
723 arg = va_arg(ap, void *);
724 va_end(ap);
725
726 return ioctl(pcm_fd, request, arg);
727}
728
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700729int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700730 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800731{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700732 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700733 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530734 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800735
736 if (usecase == NULL)
737 return -EINVAL;
738
739 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
740
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800741 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700742 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800743 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800745
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800746#ifdef DS1_DOLBY_DAP_ENABLED
747 audio_extn_dolby_set_dmid(adev);
748 audio_extn_dolby_set_endpoint(adev);
749#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700750 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700751 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530752 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700753 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530754 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530755 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
756 out = usecase->stream.out;
757 if (out && out->compr)
758 audio_extn_utils_compress_set_clk_rec_mode(usecase);
759 }
760
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800761 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700762 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700763 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700764 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800765 ALOGV("%s: exit", __func__);
766 return 0;
767}
768
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700769int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700770 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800771{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700772 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700773 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800774
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530775 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800776 return -EINVAL;
777
778 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700779 if (usecase->type == PCM_CAPTURE)
780 snd_device = usecase->in_snd_device;
781 else
782 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800783 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700784 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700785 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700786 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700787 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530788 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800789 ALOGV("%s: exit", __func__);
790 return 0;
791}
792
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700793int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700794 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800795{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530796 int i, num_devices = 0;
797 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700798 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
799
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800800 if (snd_device < SND_DEVICE_MIN ||
801 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800802 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800803 return -EINVAL;
804 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700805
806 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700807
808 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
809 ALOGE("%s: Invalid sound device returned", __func__);
810 return -EINVAL;
811 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700812 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700813 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700814 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700815 return 0;
816 }
817
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530818
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700819 if (audio_extn_spkr_prot_is_enabled())
820 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700821
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800822 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
823 audio_extn_spkr_prot_is_enabled()) {
824 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700825 adev->snd_dev_ref_cnt[snd_device]--;
826 return -EINVAL;
827 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200828 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800829 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800830 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200831 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800832 return -EINVAL;
833 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700834 } else if (platform_split_snd_device(adev->platform,
835 snd_device,
836 &num_devices,
837 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530838 for (i = 0; i < num_devices; i++) {
839 enable_snd_device(adev, new_snd_devices[i]);
840 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800841 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700842 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530843
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530844
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530845 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
846 (audio_extn_a2dp_start_playback() < 0)) {
847 ALOGE(" fail to configure A2dp control path ");
848 return -EINVAL;
849 }
850
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700851 /* due to the possibility of calibration overwrite between listen
852 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700853 audio_extn_sound_trigger_update_device_status(snd_device,
854 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530855 audio_extn_listen_update_device_status(snd_device,
856 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700857 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700858 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700859 audio_extn_sound_trigger_update_device_status(snd_device,
860 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530861 audio_extn_listen_update_device_status(snd_device,
862 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700863 return -EINVAL;
864 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300865 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700866 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530867
868 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
869 !adev->native_playback_enabled &&
870 audio_is_true_native_stream_active(adev)) {
871 ALOGD("%s: %d: napb: enabling native mode in hardware",
872 __func__, __LINE__);
873 audio_route_apply_and_update_path(adev->audio_route,
874 "true-native-mode");
875 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530876 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800877 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800878 return 0;
879}
880
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700881int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700882 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800883{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530884 int i, num_devices = 0;
885 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700886 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
887
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800888 if (snd_device < SND_DEVICE_MIN ||
889 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800890 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800891 return -EINVAL;
892 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
894 ALOGE("%s: device ref cnt is already 0", __func__);
895 return -EINVAL;
896 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700897
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700898 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700899
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700900 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
901 ALOGE("%s: Invalid sound device returned", __func__);
902 return -EINVAL;
903 }
904
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700905 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700906 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530907
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800908 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
909 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700910 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700911 } else if (platform_split_snd_device(adev->platform,
912 snd_device,
913 &num_devices,
914 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530915 for (i = 0; i < num_devices; i++) {
916 disable_snd_device(adev, new_snd_devices[i]);
917 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300918 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700919 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300920 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700921
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530922 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
923 audio_extn_a2dp_stop_playback();
924
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700925 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530926 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530927 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
928 adev->native_playback_enabled) {
929 ALOGD("%s: %d: napb: disabling native mode in hardware",
930 __func__, __LINE__);
931 audio_route_reset_and_update_path(adev->audio_route,
932 "true-native-mode");
933 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530934 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
935 adev->asrc_mode_enabled) {
936 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530937 disable_asrc_mode(adev);
938 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530939 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530940
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200941 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700942 audio_extn_sound_trigger_update_device_status(snd_device,
943 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530944 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800945 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700946 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700947
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800948 return 0;
949}
950
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700951/*
952 legend:
953 uc - existing usecase
954 new_uc - new usecase
955 d1, d11, d2 - SND_DEVICE enums
956 a1, a2 - corresponding ANDROID device enums
957 B1, B2 - backend strings
958
959case 1
960 uc->dev d1 (a1) B1
961 new_uc->dev d1 (a1), d2 (a2) B1, B2
962
963 resolution: disable and enable uc->dev on d1
964
965case 2
966 uc->dev d1 (a1) B1
967 new_uc->dev d11 (a1) B1
968
969 resolution: need to switch uc since d1 and d11 are related
970 (e.g. speaker and voice-speaker)
971 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
972
973case 3
974 uc->dev d1 (a1) B1
975 new_uc->dev d2 (a2) B2
976
977 resolution: no need to switch uc
978
979case 4
980 uc->dev d1 (a1) B1
981 new_uc->dev d2 (a2) B1
982
983 resolution: disable enable uc-dev on d2 since backends match
984 we cannot enable two streams on two different devices if they
985 share the same backend. e.g. if offload is on speaker device using
986 QUAD_MI2S backend and a low-latency stream is started on voice-handset
987 using the same backend, offload must also be switched to voice-handset.
988
989case 5
990 uc->dev d1 (a1) B1
991 new_uc->dev d1 (a1), d2 (a2) B1
992
993 resolution: disable enable uc-dev on d2 since backends match
994 we cannot enable two streams on two different devices if they
995 share the same backend.
996
997case 6
998 uc->dev d1 (a1) B1
999 new_uc->dev d2 (a1) B2
1000
1001 resolution: no need to switch
1002
1003case 7
1004 uc->dev d1 (a1), d2 (a2) B1, B2
1005 new_uc->dev d1 (a1) B1
1006
1007 resolution: no need to switch
1008
1009*/
1010static snd_device_t derive_playback_snd_device(void * platform,
1011 struct audio_usecase *uc,
1012 struct audio_usecase *new_uc,
1013 snd_device_t new_snd_device)
1014{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301015 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001016
1017 snd_device_t d1 = uc->out_snd_device;
1018 snd_device_t d2 = new_snd_device;
1019
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301020 switch (uc->type) {
1021 case TRANSCODE_LOOPBACK :
1022 a1 = uc->stream.inout->out_config.devices;
1023 a2 = new_uc->stream.inout->out_config.devices;
1024 break;
1025 default :
1026 a1 = uc->stream.out->devices;
1027 a2 = new_uc->stream.out->devices;
1028 break;
1029 }
1030
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001031 // Treat as a special case when a1 and a2 are not disjoint
1032 if ((a1 != a2) && (a1 & a2)) {
1033 snd_device_t d3[2];
1034 int num_devices = 0;
1035 int ret = platform_split_snd_device(platform,
1036 popcount(a1) > 1 ? d1 : d2,
1037 &num_devices,
1038 d3);
1039 if (ret < 0) {
1040 if (ret != -ENOSYS) {
1041 ALOGW("%s failed to split snd_device %d",
1042 __func__,
1043 popcount(a1) > 1 ? d1 : d2);
1044 }
1045 goto end;
1046 }
1047
1048 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1049 // But if it does happen, we need to give priority to d2 if
1050 // the combo devices active on the existing usecase share a backend.
1051 // This is because we cannot have a usecase active on a combo device
1052 // and a new usecase requests one device in this combo pair.
1053 if (platform_check_backends_match(d3[0], d3[1])) {
1054 return d2; // case 5
1055 } else {
1056 return d1; // case 1
1057 }
1058 } else {
1059 if (platform_check_backends_match(d1, d2)) {
1060 return d2; // case 2, 4
1061 } else {
1062 return d1; // case 6, 3
1063 }
1064 }
1065
1066end:
1067 return d2; // return whatever was calculated before.
1068}
1069
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001070static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301071 struct audio_usecase *uc_info,
1072 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001073{
1074 struct listnode *node;
1075 struct audio_usecase *usecase;
1076 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301077 snd_device_t uc_derive_snd_device;
1078 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001079 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001080 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301081 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001082 /*
1083 * This function is to make sure that all the usecases that are active on
1084 * the hardware codec backend are always routed to any one device that is
1085 * handled by the hardware codec.
1086 * For example, if low-latency and deep-buffer usecases are currently active
1087 * on speaker and out_set_parameters(headset) is received on low-latency
1088 * output, then we have to make sure deep-buffer is also switched to headset,
1089 * because of the limitation that both the devices cannot be enabled
1090 * at the same time as they share the same backend.
1091 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001092 /*
1093 * This call is to check if we need to force routing for a particular stream
1094 * If there is a backend configuration change for the device when a
1095 * new stream starts, then ADM needs to be closed and re-opened with the new
1096 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001097 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001098 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001099 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1100 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301101 /* For a2dp device reconfigure all active sessions
1102 * with new AFE encoder format based on a2dp state
1103 */
1104 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1105 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1106 audio_extn_a2dp_is_force_device_switch()) {
1107 force_routing = true;
1108 force_restart_session = true;
1109 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301110 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1111
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001112 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001113 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001114 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001115 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1116 switch_device[i] = false;
1117
1118 list_for_each(node, &adev->usecase_list) {
1119 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001120
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301121 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1122 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301123 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301124 platform_get_snd_device_name(usecase->out_snd_device),
1125 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301126 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1127 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1128 usecase, uc_info, snd_device);
1129 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1130 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1131 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1132 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1133 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1134 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1135 ((force_restart_session) ||
1136 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301137 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1138 __func__, use_case_table[usecase->id],
1139 platform_get_snd_device_name(usecase->out_snd_device));
1140 disable_audio_route(adev, usecase);
1141 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301142 /* Enable existing usecase on derived playback device */
1143 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301144 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301145 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001146 }
1147 }
1148
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301149 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1150 num_uc_to_switch);
1151
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001153 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001154
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301155 /* Make sure the previous devices to be disabled first and then enable the
1156 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001157 list_for_each(node, &adev->usecase_list) {
1158 usecase = node_to_item(node, struct audio_usecase, list);
1159 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001160 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001161 }
1162 }
1163
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001164 list_for_each(node, &adev->usecase_list) {
1165 usecase = node_to_item(node, struct audio_usecase, list);
1166 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301167 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001168 }
1169 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001170
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001171 /* Re-route all the usecases on the shared backend other than the
1172 specified usecase to new snd devices */
1173 list_for_each(node, &adev->usecase_list) {
1174 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301175 /* Update the out_snd_device only before enabling the audio route */
1176 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301177 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301178 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301179 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301180 use_case_table[usecase->id],
1181 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001182 /* Update voc calibration before enabling VoIP route */
1183 if (usecase->type == VOIP_CALL)
1184 status = platform_switch_voice_call_device_post(adev->platform,
1185 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001186 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301187 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301188 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001189 }
1190 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001191 }
1192}
1193
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301194static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001195 struct audio_usecase *uc_info,
1196 snd_device_t snd_device)
1197{
1198 struct listnode *node;
1199 struct audio_usecase *usecase;
1200 bool switch_device[AUDIO_USECASE_MAX];
1201 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301202 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001203 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001204
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301205 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1206 snd_device);
1207 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301208
1209 /*
1210 * Make sure out devices is checked against out codec backend device and
1211 * also in devices against in codec backend. Checking out device against in
1212 * codec backend or vice versa causes issues.
1213 */
1214 if (uc_info->type == PCM_CAPTURE)
1215 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001216 /*
1217 * This function is to make sure that all the active capture usecases
1218 * are always routed to the same input sound device.
1219 * For example, if audio-record and voice-call usecases are currently
1220 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1221 * is received for voice call then we have to make sure that audio-record
1222 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1223 * because of the limitation that two devices cannot be enabled
1224 * at the same time if they share the same backend.
1225 */
1226 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1227 switch_device[i] = false;
1228
1229 list_for_each(node, &adev->usecase_list) {
1230 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301231 /*
1232 * TODO: Enhance below condition to handle BT sco/USB multi recording
1233 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001234 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001235 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301236 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301237 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301238 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301239 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001240 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001241 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1242 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001243 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001244 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001245 switch_device[usecase->id] = true;
1246 num_uc_to_switch++;
1247 }
1248 }
1249
1250 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001251 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001252
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301253 /* Make sure the previous devices to be disabled first and then enable the
1254 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001255 list_for_each(node, &adev->usecase_list) {
1256 usecase = node_to_item(node, struct audio_usecase, list);
1257 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001258 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001259 }
1260 }
1261
1262 list_for_each(node, &adev->usecase_list) {
1263 usecase = node_to_item(node, struct audio_usecase, list);
1264 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001265 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001266 }
1267 }
1268
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001269 /* Re-route all the usecases on the shared backend other than the
1270 specified usecase to new snd devices */
1271 list_for_each(node, &adev->usecase_list) {
1272 usecase = node_to_item(node, struct audio_usecase, list);
1273 /* Update the in_snd_device only before enabling the audio route */
1274 if (switch_device[usecase->id] ) {
1275 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001276 if (usecase->type != VOICE_CALL) {
1277 /* Update voc calibration before enabling VoIP route */
1278 if (usecase->type == VOIP_CALL)
1279 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001280 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001281 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301282 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001283 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001284 }
1285 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001286 }
1287}
1288
Mingming Yin3a941d42016-02-17 18:08:05 -08001289static void reset_hdmi_sink_caps(struct stream_out *out) {
1290 int i = 0;
1291
1292 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1293 out->supported_channel_masks[i] = 0;
1294 }
1295 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1296 out->supported_formats[i] = 0;
1297 }
1298 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1299 out->supported_sample_rates[i] = 0;
1300 }
1301}
1302
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001303/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001304static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001305{
Mingming Yin3a941d42016-02-17 18:08:05 -08001306 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001307 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001308
Mingming Yin3a941d42016-02-17 18:08:05 -08001309 reset_hdmi_sink_caps(out);
1310
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001311 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001312 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001313 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001314 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001315 }
1316
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001317 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001318 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001319 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001320 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001321 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1322 case 6:
1323 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1324 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1325 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1326 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1327 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1328 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001329 break;
1330 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001331 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001332 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001333 break;
1334 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001335
1336 // check channel format caps
1337 i = 0;
1338 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1339 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1340 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1341 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1342 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1343 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1344 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1345 }
1346
Ben Romberger1aaaf862017-04-06 17:49:46 -07001347 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1348 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1349 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1350 }
1351
Mingming Yin3a941d42016-02-17 18:08:05 -08001352 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1353 ALOGV(":%s HDMI supports DTS format", __func__);
1354 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1355 }
1356
1357 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1358 ALOGV(":%s HDMI supports DTS HD format", __func__);
1359 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1360 }
1361
Naresh Tanniru928f0862017-04-07 16:44:23 -07001362 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1363 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1364 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1365 }
1366
Mingming Yin3a941d42016-02-17 18:08:05 -08001367
1368 // check sample rate caps
1369 i = 0;
1370 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1371 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1372 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1373 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1374 }
1375 }
1376
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001377 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001378}
1379
Alexy Josephb1379942016-01-29 15:49:38 -08001380audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001381 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001382{
1383 struct audio_usecase *usecase;
1384 struct listnode *node;
1385
1386 list_for_each(node, &adev->usecase_list) {
1387 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001388 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001389 ALOGV("%s: usecase id %d", __func__, usecase->id);
1390 return usecase->id;
1391 }
1392 }
1393 return USECASE_INVALID;
1394}
1395
Alexy Josephb1379942016-01-29 15:49:38 -08001396struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001397 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001398{
1399 struct audio_usecase *usecase;
1400 struct listnode *node;
1401
1402 list_for_each(node, &adev->usecase_list) {
1403 usecase = node_to_item(node, struct audio_usecase, list);
1404 if (usecase->id == uc_id)
1405 return usecase;
1406 }
1407 return NULL;
1408}
1409
Dhananjay Kumard4833242016-10-06 22:09:12 +05301410struct stream_in *get_next_active_input(const struct audio_device *adev)
1411{
1412 struct audio_usecase *usecase;
1413 struct listnode *node;
1414
1415 list_for_each_reverse(node, &adev->usecase_list) {
1416 usecase = node_to_item(node, struct audio_usecase, list);
1417 if (usecase->type == PCM_CAPTURE)
1418 return usecase->stream.in;
1419 }
1420 return NULL;
1421}
1422
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301423/*
1424 * is a true native playback active
1425 */
1426bool audio_is_true_native_stream_active(struct audio_device *adev)
1427{
1428 bool active = false;
1429 int i = 0;
1430 struct listnode *node;
1431
1432 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1433 ALOGV("%s:napb: not in true mode or non hdphones device",
1434 __func__);
1435 active = false;
1436 goto exit;
1437 }
1438
1439 list_for_each(node, &adev->usecase_list) {
1440 struct audio_usecase *uc;
1441 uc = node_to_item(node, struct audio_usecase, list);
1442 struct stream_out *curr_out =
1443 (struct stream_out*) uc->stream.out;
1444
1445 if (curr_out && PCM_PLAYBACK == uc->type) {
1446 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1447 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1448 uc->id, curr_out->sample_rate,
1449 curr_out->bit_width,
1450 platform_get_snd_device_name(uc->out_snd_device));
1451
1452 if (is_offload_usecase(uc->id) &&
1453 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1454 active = true;
1455 ALOGD("%s:napb:native stream detected", __func__);
1456 }
1457 }
1458 }
1459exit:
1460 return active;
1461}
1462
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001463uint32_t adev_get_dsp_bit_width_enforce_mode()
1464{
1465 if (adev == NULL) {
1466 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1467 return 0;
1468 }
1469 return adev->dsp_bit_width_enforce_mode;
1470}
1471
1472static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1473{
1474 char value[PROPERTY_VALUE_MAX];
1475 int trial;
1476 uint32_t dsp_bit_width_enforce_mode = 0;
1477
1478 if (!mixer) {
1479 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1480 __func__);
1481 return 0;
1482 }
1483
1484 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1485 value, NULL) > 0) {
1486 trial = atoi(value);
1487 switch (trial) {
1488 case 16:
1489 dsp_bit_width_enforce_mode = 16;
1490 break;
1491 case 24:
1492 dsp_bit_width_enforce_mode = 24;
1493 break;
1494 case 32:
1495 dsp_bit_width_enforce_mode = 32;
1496 break;
1497 default:
1498 dsp_bit_width_enforce_mode = 0;
1499 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1500 break;
1501 }
1502 }
1503
1504 return dsp_bit_width_enforce_mode;
1505}
1506
1507static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1508 uint32_t enforce_mode,
1509 bool enable)
1510{
1511 struct mixer_ctl *ctl = NULL;
1512 const char *mixer_ctl_name = "ASM Bit Width";
1513 uint32_t asm_bit_width_mode = 0;
1514
1515 if (enforce_mode == 0) {
1516 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1517 return;
1518 }
1519
1520 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1521 if (!ctl) {
1522 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1523 __func__, mixer_ctl_name);
1524 return;
1525 }
1526
1527 if (enable)
1528 asm_bit_width_mode = enforce_mode;
1529 else
1530 asm_bit_width_mode = 0;
1531
1532 ALOGV("%s DSP bit width feature status is %d width=%d",
1533 __func__, enable, asm_bit_width_mode);
1534 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1535 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1536 asm_bit_width_mode);
1537
1538 return;
1539}
1540
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301541/*
1542 * if native DSD playback active
1543 */
1544bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1545{
1546 bool active = false;
1547 struct listnode *node = NULL;
1548 struct audio_usecase *uc = NULL;
1549 struct stream_out *curr_out = NULL;
1550
1551 list_for_each(node, &adev->usecase_list) {
1552 uc = node_to_item(node, struct audio_usecase, list);
1553 curr_out = (struct stream_out*) uc->stream.out;
1554
1555 if (curr_out && PCM_PLAYBACK == uc->type &&
1556 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1557 active = true;
1558 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301559 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301560 }
1561 }
1562 return active;
1563}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301564
1565static bool force_device_switch(struct audio_usecase *usecase)
1566{
1567 bool ret = false;
1568 bool is_it_true_mode = false;
1569
1570 if (is_offload_usecase(usecase->id) &&
1571 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001572 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1573 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1574 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301575 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1576 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1577 (!is_it_true_mode && adev->native_playback_enabled)){
1578 ret = true;
1579 ALOGD("napb: time to toggle native mode");
1580 }
1581 }
1582
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301583 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301584 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1585 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301586 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001587 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301588 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301589 ALOGD("Force a2dp device switch to update new encoder config");
1590 ret = true;
1591 }
1592
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301593 return ret;
1594}
1595
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301596bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1597{
1598 bool ret=false;
1599 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1600 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1601 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1602 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1603 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1604 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1605 ret = true;
1606
1607 return ret;
1608}
1609
1610bool is_a2dp_device(snd_device_t out_snd_device)
1611{
1612 bool ret=false;
1613 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1614 ret = true;
1615
1616 return ret;
1617}
1618
1619bool is_bt_soc_on(struct audio_device *adev)
1620{
1621 struct mixer_ctl *ctl;
1622 char *mixer_ctl_name = "BT SOC status";
1623 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1624 bool bt_soc_status = true;
1625 if (!ctl) {
1626 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1627 __func__, mixer_ctl_name);
1628 /*This is to ensure we dont break targets which dont have the kernel change*/
1629 return true;
1630 }
1631 bt_soc_status = mixer_ctl_get_value(ctl, 0);
1632 ALOGD("BT SOC status: %d",bt_soc_status);
1633 return bt_soc_status;
1634}
1635
1636int out_standby_l(struct audio_stream *stream);
1637
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001638int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001639{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001640 snd_device_t out_snd_device = SND_DEVICE_NONE;
1641 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001642 struct audio_usecase *usecase = NULL;
1643 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001644 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001645 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301646 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001647 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001648 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301650 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1651
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001652 usecase = get_usecase_from_list(adev, uc_id);
1653 if (usecase == NULL) {
1654 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1655 return -EINVAL;
1656 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001658 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001659 (usecase->type == VOIP_CALL) ||
1660 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301661 if(usecase->stream.out == NULL) {
1662 ALOGE("%s: stream.out is NULL", __func__);
1663 return -EINVAL;
1664 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001665 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001666 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001667 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001668 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301669 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
1670 if (usecase->stream.inout == NULL) {
1671 ALOGE("%s: stream.inout is NULL", __func__);
1672 return -EINVAL;
1673 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301674 stream_out.devices = usecase->stream.inout->out_config.devices;
1675 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
1676 stream_out.format = usecase->stream.inout->out_config.format;
1677 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
1678 out_snd_device = platform_get_output_snd_device(adev->platform,
1679 &stream_out);
1680 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301681 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001682 } else {
1683 /*
1684 * If the voice call is active, use the sound devices of voice call usecase
1685 * so that it would not result any device switch. All the usecases will
1686 * be switched to new device when select_devices() is called for voice call
1687 * usecase. This is to avoid switching devices for voice call when
1688 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001689 * choose voice call device only if the use case device is
1690 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001691 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001692 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001693 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001694 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001695 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1696 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301697 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1698 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001699 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001700 in_snd_device = vc_usecase->in_snd_device;
1701 out_snd_device = vc_usecase->out_snd_device;
1702 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001703 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001704 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001705 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001706 if ((voip_usecase != NULL) &&
1707 (usecase->type == PCM_PLAYBACK) &&
1708 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001709 out_snd_device_backend_match = platform_check_backends_match(
1710 voip_usecase->out_snd_device,
1711 platform_get_output_snd_device(
1712 adev->platform,
1713 usecase->stream.out));
1714 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001715 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001716 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1717 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001718 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001719 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001720 in_snd_device = voip_usecase->in_snd_device;
1721 out_snd_device = voip_usecase->out_snd_device;
1722 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001723 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001724 hfp_ucid = audio_extn_hfp_get_usecase();
1725 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001726 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001727 in_snd_device = hfp_usecase->in_snd_device;
1728 out_snd_device = hfp_usecase->out_snd_device;
1729 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001730 }
1731 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301732 if (usecase->stream.out == NULL) {
1733 ALOGE("%s: stream.out is NULL", __func__);
1734 return -EINVAL;
1735 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001736 usecase->devices = usecase->stream.out->devices;
1737 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001738 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001739 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001740 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001741 if (usecase->stream.out == adev->primary_output &&
1742 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001743 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001744 select_devices(adev, adev->active_input->usecase);
1745 }
1746 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001747 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301748 if (usecase->stream.in == NULL) {
1749 ALOGE("%s: stream.in is NULL", __func__);
1750 return -EINVAL;
1751 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001752 usecase->devices = usecase->stream.in->device;
1753 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001754 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001755 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001756 if (adev->active_input &&
1757 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301758 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1759 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1760 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001761 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001762 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001763 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1764 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001765 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001766 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001767 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001768 }
1769 }
1770
1771 if (out_snd_device == usecase->out_snd_device &&
1772 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301773
1774 if (!force_device_switch(usecase))
1775 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776 }
1777
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301778 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
1779 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
1780 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1781 return 0;
1782 }
1783
sangwoobc677242013-08-08 16:53:43 +09001784 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001785 out_snd_device, platform_get_snd_device_name(out_snd_device),
1786 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788 /*
1789 * Limitation: While in call, to do a device switch we need to disable
1790 * and enable both RX and TX devices though one of them is same as current
1791 * device.
1792 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001793 if ((usecase->type == VOICE_CALL) &&
1794 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1795 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001796 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001797 }
1798
1799 if (((usecase->type == VOICE_CALL) ||
1800 (usecase->type == VOIP_CALL)) &&
1801 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1802 /* Disable sidetone only if voice/voip call already exists */
1803 if (voice_is_call_state_active(adev) ||
1804 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001805 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001806
1807 /* Disable aanc only if voice call exists */
1808 if (voice_is_call_state_active(adev))
1809 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001810 }
1811
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05301812 if ((usecase->out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
1813 (!audio_extn_a2dp_is_ready())) {
1814 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
1815 usecase->out_snd_device = SND_DEVICE_OUT_SPEAKER;
1816 }
1817
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001818 /* Disable current sound devices */
1819 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001820 disable_audio_route(adev, usecase);
1821 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001822 }
1823
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001824 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001825 disable_audio_route(adev, usecase);
1826 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001827 }
1828
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001829 /* Applicable only on the targets that has external modem.
1830 * New device information should be sent to modem before enabling
1831 * the devices to reduce in-call device switch time.
1832 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001833 if ((usecase->type == VOICE_CALL) &&
1834 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1835 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001836 status = platform_switch_voice_call_enable_device_config(adev->platform,
1837 out_snd_device,
1838 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001839 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001840
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001841 /* Enable new sound devices */
1842 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001843 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301844 if (platform_check_codec_asrc_support(adev->platform))
1845 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001846 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847 }
1848
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001849 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301850 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001851 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001852 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001853
Avinash Vaish71a8b972014-07-24 15:36:33 +05301854 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001855 status = platform_switch_voice_call_device_post(adev->platform,
1856 out_snd_device,
1857 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301858 enable_audio_route_for_voice_usecases(adev, usecase);
1859 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001860
sangwoo170731f2013-06-08 15:36:36 +09001861 usecase->in_snd_device = in_snd_device;
1862 usecase->out_snd_device = out_snd_device;
1863
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301864 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1865 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301866 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001867 if ((24 == usecase->stream.out->bit_width) &&
1868 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1869 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1870 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1871 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1872 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1873 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1874 /*
1875 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1876 * configured device sample rate, if not update the COPP rate to be equal to the
1877 * device sample rate, else open COPP at stream sample rate
1878 */
1879 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1880 usecase->stream.out->sample_rate,
1881 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301882 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1883 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001884 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1885 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1886 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1887 }
1888
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001889 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001890 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001891 audio_extn_gef_notify_device_config(
1892 usecase->stream.out->devices,
1893 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001894 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001895 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001896 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301897 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001898 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001899
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001900 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001901 /* Enable aanc only if voice call exists */
1902 if (voice_is_call_state_active(adev))
1903 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1904
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001905 /* Enable sidetone only if other voice/voip call already exists */
1906 if (voice_is_call_state_active(adev) ||
1907 voice_extn_compress_voip_is_started(adev))
1908 voice_set_sidetone(adev, out_snd_device, true);
1909 }
1910
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001911 /* Applicable only on the targets that has external modem.
1912 * Enable device command should be sent to modem only after
1913 * enabling voice call mixer controls
1914 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001915 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001916 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1917 out_snd_device,
1918 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301919
1920 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
1921
1922 if (usecase->type == VOIP_CALL) {
1923 if (adev->active_input != NULL &&
1924 !adev->active_input->standby) {
1925 if (is_bt_soc_on(adev) == false){
1926 ALOGD("BT SCO MIC disconnected while in connection");
1927 if (adev->active_input->pcm != NULL)
1928 pcm_stop(adev->active_input->pcm);
1929 }
1930 }
1931 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
1932 && usecase->stream.out->started) {
1933 if (is_bt_soc_on(adev) == false) {
1934 ALOGD("BT SCO/A2DP disconnected while in connection");
1935 out_standby_l(&usecase->stream.out->stream.common);
1936 }
1937 }
1938 } else if ((usecase->stream.out != NULL) &&
1939 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
1940 usecase->stream.out->started) {
1941 if (is_bt_soc_on(adev) == false) {
1942 ALOGD("BT SCO/A2dp disconnected while in connection");
1943 out_standby_l(&usecase->stream.out->stream.common);
1944 }
1945 }
1946 }
1947
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301948 ALOGD("%s: done",__func__);
1949
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950 return status;
1951}
1952
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953static int stop_input_stream(struct stream_in *in)
1954{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301955 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956 struct audio_usecase *uc_info;
1957 struct audio_device *adev = in->dev;
1958
Eric Laurent994a6932013-07-17 11:51:42 -07001959 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001960 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961 uc_info = get_usecase_from_list(adev, in->usecase);
1962 if (uc_info == NULL) {
1963 ALOGE("%s: Could not find the usecase (%d) in the list",
1964 __func__, in->usecase);
1965 return -EINVAL;
1966 }
1967
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001968 /* Close in-call recording streams */
1969 voice_check_and_stop_incall_rec_usecase(adev, in);
1970
Eric Laurent150dbfe2013-02-27 14:31:02 -08001971 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001972 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001973
1974 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001975 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001977 list_remove(&uc_info->list);
1978 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001980 adev->active_input = get_next_active_input(adev);
1981
Eric Laurent994a6932013-07-17 11:51:42 -07001982 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983 return ret;
1984}
1985
1986int start_input_stream(struct stream_in *in)
1987{
1988 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001989 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990 struct audio_usecase *uc_info;
1991 struct audio_device *adev = in->dev;
1992
Mingming Yin2664a5b2015-09-03 10:53:11 -07001993 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1994 if (get_usecase_from_list(adev, usecase) == NULL)
1995 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301996 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1997 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001998
Naresh Tanniru80659832014-06-04 18:17:56 +05301999
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302000 if (CARD_STATUS_OFFLINE == in->card_status||
2001 CARD_STATUS_OFFLINE == adev->card_status) {
2002 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302003 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302004 goto error_config;
2005 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302006
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302007 if (audio_is_bluetooth_sco_device(in->device)) {
2008 if (!adev->bt_sco_on) {
2009 ALOGE("%s: SCO profile is not ready, return error", __func__);
2010 ret = -EIO;
2011 goto error_config;
2012 }
2013 }
2014
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002015 /* Check if source matches incall recording usecase criteria */
2016 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2017 if (ret)
2018 goto error_config;
2019 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002020 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2021
2022 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2023 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2024 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002025 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002026 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002027
Eric Laurentb23d5282013-05-14 15:27:20 -07002028 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029 if (in->pcm_device_id < 0) {
2030 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2031 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002032 ret = -EINVAL;
2033 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002034 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002035
2036 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002038
2039 if (!uc_info) {
2040 ret = -ENOMEM;
2041 goto error_config;
2042 }
2043
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044 uc_info->id = in->usecase;
2045 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002046 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002047 uc_info->devices = in->device;
2048 uc_info->in_snd_device = SND_DEVICE_NONE;
2049 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002051 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302052 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2053 adev->perf_lock_opts,
2054 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002055 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302057 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
2058 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002059
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302060 if (audio_extn_cin_attached_usecase(in->usecase)) {
2061 ret = audio_extn_cin_start_input_stream(in);
2062 if (ret)
2063 goto error_open;
2064 else
2065 goto done_open;
2066 }
2067
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002068 unsigned int flags = PCM_IN;
2069 unsigned int pcm_open_retry_count = 0;
2070
2071 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2072 flags |= PCM_MMAP | PCM_NOIRQ;
2073 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002074 } else if (in->realtime) {
2075 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002076 }
2077
2078 while (1) {
2079 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
2080 flags, &in->config);
2081 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2082 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2083 if (in->pcm != NULL) {
2084 pcm_close(in->pcm);
2085 in->pcm = NULL;
2086 }
2087 if (pcm_open_retry_count-- == 0) {
2088 ret = -EIO;
2089 goto error_open;
2090 }
2091 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2092 continue;
2093 }
2094 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002095 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002096
2097 ALOGV("%s: pcm_prepare", __func__);
2098 ret = pcm_prepare(in->pcm);
2099 if (ret < 0) {
2100 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2101 pcm_close(in->pcm);
2102 in->pcm = NULL;
2103 goto error_open;
2104 }
2105
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002106 register_in_stream(in);
2107 if (in->realtime) {
2108 ret = pcm_start(in->pcm);
2109 if (ret < 0)
2110 goto error_open;
2111 }
2112
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302113done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302114 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002115 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002116
Eric Laurentc8400632013-02-14 19:04:54 -08002117 return ret;
2118
2119error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302120 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002122error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302123 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302124 /*
2125 * sleep 50ms to allow sufficient time for kernel
2126 * drivers to recover incases like SSR.
2127 */
2128 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002129 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002130
2131 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002132}
2133
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002134void lock_input_stream(struct stream_in *in)
2135{
2136 pthread_mutex_lock(&in->pre_lock);
2137 pthread_mutex_lock(&in->lock);
2138 pthread_mutex_unlock(&in->pre_lock);
2139}
2140
2141void lock_output_stream(struct stream_out *out)
2142{
2143 pthread_mutex_lock(&out->pre_lock);
2144 pthread_mutex_lock(&out->lock);
2145 pthread_mutex_unlock(&out->pre_lock);
2146}
2147
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002148/* must be called with out->lock locked */
2149static int send_offload_cmd_l(struct stream_out* out, int command)
2150{
2151 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2152
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002153 if (!cmd) {
2154 ALOGE("failed to allocate mem for command 0x%x", command);
2155 return -ENOMEM;
2156 }
2157
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002158 ALOGVV("%s %d", __func__, command);
2159
2160 cmd->cmd = command;
2161 list_add_tail(&out->offload_cmd_list, &cmd->node);
2162 pthread_cond_signal(&out->offload_cond);
2163 return 0;
2164}
2165
2166/* must be called iwth out->lock locked */
2167static void stop_compressed_output_l(struct stream_out *out)
2168{
2169 out->offload_state = OFFLOAD_STATE_IDLE;
2170 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002171 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002172 if (out->compr != NULL) {
2173 compress_stop(out->compr);
2174 while (out->offload_thread_blocked) {
2175 pthread_cond_wait(&out->cond, &out->lock);
2176 }
2177 }
2178}
2179
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002180bool is_offload_usecase(audio_usecase_t uc_id)
2181{
2182 unsigned int i;
2183 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2184 if (uc_id == offload_usecases[i])
2185 return true;
2186 }
2187 return false;
2188}
2189
Dhananjay Kumarac341582017-02-23 23:42:25 +05302190static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002191{
vivek mehta446c3962015-09-14 10:57:35 -07002192 audio_usecase_t ret_uc = USECASE_INVALID;
2193 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002194 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002195 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302196 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002197 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2198 else
2199 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002200
vivek mehta446c3962015-09-14 10:57:35 -07002201 pthread_mutex_lock(&adev->lock);
2202 if (get_usecase_from_list(adev, ret_uc) != NULL)
2203 ret_uc = USECASE_INVALID;
2204 pthread_mutex_unlock(&adev->lock);
2205
2206 return ret_uc;
2207 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002208
2209 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002210 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2211 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2212 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2213 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002214 break;
2215 }
2216 }
vivek mehta446c3962015-09-14 10:57:35 -07002217
2218 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2219 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002220}
2221
2222static void free_offload_usecase(struct audio_device *adev,
2223 audio_usecase_t uc_id)
2224{
vivek mehta446c3962015-09-14 10:57:35 -07002225 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002226 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002227
2228 if (!adev->multi_offload_enable)
2229 return;
2230
2231 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2232 if (offload_usecases[offload_uc_index] == uc_id) {
2233 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002234 break;
2235 }
2236 }
2237 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2238}
2239
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002240static void *offload_thread_loop(void *context)
2241{
2242 struct stream_out *out = (struct stream_out *) context;
2243 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002244 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002245
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002246 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2247 set_sched_policy(0, SP_FOREGROUND);
2248 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2249
2250 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002251 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002252 for (;;) {
2253 struct offload_cmd *cmd = NULL;
2254 stream_callback_event_t event;
2255 bool send_callback = false;
2256
2257 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2258 __func__, list_empty(&out->offload_cmd_list),
2259 out->offload_state);
2260 if (list_empty(&out->offload_cmd_list)) {
2261 ALOGV("%s SLEEPING", __func__);
2262 pthread_cond_wait(&out->offload_cond, &out->lock);
2263 ALOGV("%s RUNNING", __func__);
2264 continue;
2265 }
2266
2267 item = list_head(&out->offload_cmd_list);
2268 cmd = node_to_item(item, struct offload_cmd, node);
2269 list_remove(item);
2270
2271 ALOGVV("%s STATE %d CMD %d out->compr %p",
2272 __func__, out->offload_state, cmd->cmd, out->compr);
2273
2274 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2275 free(cmd);
2276 break;
2277 }
2278
2279 if (out->compr == NULL) {
2280 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002281 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002282 pthread_cond_signal(&out->cond);
2283 continue;
2284 }
2285 out->offload_thread_blocked = true;
2286 pthread_mutex_unlock(&out->lock);
2287 send_callback = false;
2288 switch(cmd->cmd) {
2289 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002290 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002291 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002292 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002293 send_callback = true;
2294 event = STREAM_CBK_EVENT_WRITE_READY;
2295 break;
2296 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002297 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302298 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002299 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302300 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002301 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302302 if (ret < 0)
2303 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302304 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302305 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002306 compress_drain(out->compr);
2307 else
2308 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302309 if (ret != -ENETRESET) {
2310 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302311 pthread_mutex_lock(&out->lock);
2312 out->send_new_metadata = 1;
2313 out->send_next_track_params = true;
2314 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302315 event = STREAM_CBK_EVENT_DRAIN_READY;
2316 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2317 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302318 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002319 break;
2320 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002321 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002322 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002323 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002324 send_callback = true;
2325 event = STREAM_CBK_EVENT_DRAIN_READY;
2326 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302327 case OFFLOAD_CMD_ERROR:
2328 ALOGD("copl(%p): sending error callback to AF", out);
2329 send_callback = true;
2330 event = STREAM_CBK_EVENT_ERROR;
2331 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002332 default:
2333 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2334 break;
2335 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002336 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002337 out->offload_thread_blocked = false;
2338 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002339 if (send_callback && out->client_callback) {
2340 ALOGVV("%s: sending client_callback event %d", __func__, event);
2341 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002342 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 free(cmd);
2344 }
2345
2346 pthread_cond_signal(&out->cond);
2347 while (!list_empty(&out->offload_cmd_list)) {
2348 item = list_head(&out->offload_cmd_list);
2349 list_remove(item);
2350 free(node_to_item(item, struct offload_cmd, node));
2351 }
2352 pthread_mutex_unlock(&out->lock);
2353
2354 return NULL;
2355}
2356
2357static int create_offload_callback_thread(struct stream_out *out)
2358{
2359 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2360 list_init(&out->offload_cmd_list);
2361 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2362 offload_thread_loop, out);
2363 return 0;
2364}
2365
2366static int destroy_offload_callback_thread(struct stream_out *out)
2367{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002368 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002369 stop_compressed_output_l(out);
2370 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2371
2372 pthread_mutex_unlock(&out->lock);
2373 pthread_join(out->offload_thread, (void **) NULL);
2374 pthread_cond_destroy(&out->offload_cond);
2375
2376 return 0;
2377}
2378
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002379static int stop_output_stream(struct stream_out *out)
2380{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302381 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382 struct audio_usecase *uc_info;
2383 struct audio_device *adev = out->dev;
2384
Eric Laurent994a6932013-07-17 11:51:42 -07002385 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002386 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002387 uc_info = get_usecase_from_list(adev, out->usecase);
2388 if (uc_info == NULL) {
2389 ALOGE("%s: Could not find the usecase (%d) in the list",
2390 __func__, out->usecase);
2391 return -EINVAL;
2392 }
2393
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002394 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302395 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002396 if (adev->visualizer_stop_output != NULL)
2397 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002398
2399 audio_extn_dts_remove_state_notifier_node(out->usecase);
2400
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002401 if (adev->offload_effects_stop_output != NULL)
2402 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2403 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002404
Eric Laurent150dbfe2013-02-27 14:31:02 -08002405 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002406 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002407
2408 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002409 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002410
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002411 if (is_offload_usecase(out->usecase)) {
2412 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2413 adev->dsp_bit_width_enforce_mode,
2414 false);
2415 }
2416
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002417 list_remove(&uc_info->list);
2418 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302419 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002420 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302421 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002422 ALOGV("Disable passthrough , reset mixer to pcm");
2423 /* NO_PASSTHROUGH */
2424 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002425 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002426 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2427 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002428
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302429 /* Must be called after removing the usecase from list */
2430 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302431 audio_extn_keep_alive_start();
2432
Siddartha Shaik15b84ea2017-08-07 12:29:25 +05302433 if (audio_extn_ip_hdlr_intf_supported(out->format, audio_extn_passthru_is_direct_passthrough(out)) && out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002434 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2435 if (ret < 0)
2436 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2437 }
2438
Eric Laurent994a6932013-07-17 11:51:42 -07002439 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440 return ret;
2441}
2442
2443int start_output_stream(struct stream_out *out)
2444{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002445 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002446 struct audio_usecase *uc_info;
2447 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002448 char mixer_ctl_name[128];
2449 struct mixer_ctl *ctl = NULL;
2450 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302451 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002453 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2454 ret = -EINVAL;
2455 goto error_config;
2456 }
2457
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302458 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2459 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2460 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302461
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302462 if (CARD_STATUS_OFFLINE == out->card_status ||
2463 CARD_STATUS_OFFLINE == adev->card_status) {
2464 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302465 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302466 goto error_config;
2467 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302468
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302469 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2470 if (!audio_extn_a2dp_is_ready()) {
2471 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302472 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302473 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302474 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2475 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2476 ret = -EAGAIN;
2477 goto error_config;
2478 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302479 }
2480 }
2481 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302482 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2483 if (!adev->bt_sco_on) {
2484 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2485 //combo usecase just by pass a2dp
2486 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
2487 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2488 } else {
2489 ALOGE("%s: SCO profile is not ready, return error", __func__);
2490 ret = -EAGAIN;
2491 goto error_config;
2492 }
2493 }
2494 }
2495
Eric Laurentb23d5282013-05-14 15:27:20 -07002496 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497 if (out->pcm_device_id < 0) {
2498 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2499 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002500 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002501 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502 }
2503
2504 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002505
2506 if (!uc_info) {
2507 ret = -ENOMEM;
2508 goto error_config;
2509 }
2510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 uc_info->id = out->usecase;
2512 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002513 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002514 uc_info->devices = out->devices;
2515 uc_info->in_snd_device = SND_DEVICE_NONE;
2516 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002517 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302519 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2520 adev->perf_lock_opts,
2521 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302522
2523 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2524 audio_extn_keep_alive_stop();
2525 if (audio_extn_passthru_is_enabled() &&
2526 audio_extn_passthru_is_passthrough_stream(out)) {
2527 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302528 }
2529 }
2530
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302531 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2532 (!audio_extn_a2dp_is_ready())) {
2533 if (!a2dp_combo) {
2534 check_a2dp_restore_l(adev, out, false);
2535 } else {
2536 audio_devices_t dev = out->devices;
2537 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2538 select_devices(adev, out->usecase);
2539 out->devices = dev;
2540 }
2541 } else {
2542 select_devices(adev, out->usecase);
2543 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002544
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002545 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2546 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002547 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002548 unsigned int flags = PCM_OUT;
2549 unsigned int pcm_open_retry_count = 0;
2550 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2551 flags |= PCM_MMAP | PCM_NOIRQ;
2552 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002553 } else if (out->realtime) {
2554 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002555 } else
2556 flags |= PCM_MONOTONIC;
2557
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002558 if ((adev->vr_audio_mode_enabled) &&
2559 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2560 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2561 "PCM_Dev %d Topology", out->pcm_device_id);
2562 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2563 if (!ctl) {
2564 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2565 __func__, mixer_ctl_name);
2566 } else {
2567 //if success use ULLPP
2568 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2569 __func__, mixer_ctl_name, out->pcm_device_id);
2570 //There is a still a possibility that some sessions
2571 // that request for FAST|RAW when 3D audio is active
2572 //can go through ULLPP. Ideally we expects apps to
2573 //listen to audio focus and stop concurrent playback
2574 //Also, we will look for mode flag (voice_in_communication)
2575 //before enabling the realtime flag.
2576 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2577 }
2578 }
2579
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002580 while (1) {
2581 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2582 flags, &out->config);
2583 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2584 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2585 if (out->pcm != NULL) {
2586 pcm_close(out->pcm);
2587 out->pcm = NULL;
2588 }
2589 if (pcm_open_retry_count-- == 0) {
2590 ret = -EIO;
2591 goto error_open;
2592 }
2593 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2594 continue;
2595 }
2596 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002597 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002598
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002599 ALOGV("%s: pcm_prepare", __func__);
2600 if (pcm_is_ready(out->pcm)) {
2601 ret = pcm_prepare(out->pcm);
2602 if (ret < 0) {
2603 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2604 pcm_close(out->pcm);
2605 out->pcm = NULL;
2606 goto error_open;
2607 }
2608 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302609 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302610 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
2611
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002612 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002613 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302614 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002615 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2616 adev->dsp_bit_width_enforce_mode,
2617 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002619 out->compr = compress_open(adev->snd_card,
2620 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002621 COMPRESS_IN, &out->compr_config);
2622 if (out->compr && !is_compress_ready(out->compr)) {
2623 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2624 compress_close(out->compr);
2625 out->compr = NULL;
2626 ret = -EIO;
2627 goto error_open;
2628 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302629 /* compress_open sends params of the track, so reset the flag here */
2630 out->is_compr_metadata_avail = false;
2631
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002632 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002633 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002634
Fred Oh3f43e742015-03-04 18:42:34 -08002635 /* Since small bufs uses blocking writes, a write will be blocked
2636 for the default max poll time (20s) in the event of an SSR.
2637 Reduce the poll time to observe and deal with SSR faster.
2638 */
Ashish Jain5106d362016-05-11 19:23:33 +05302639 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002640 compress_set_max_poll_wait(out->compr, 1000);
2641 }
2642
Manish Dewangan69426c82017-01-30 17:35:36 +05302643 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302644 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05302645
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002646 audio_extn_dts_create_state_notifier_node(out->usecase);
2647 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2648 popcount(out->channel_mask),
2649 out->playback_started);
2650
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002651#ifdef DS1_DOLBY_DDP_ENABLED
2652 if (audio_extn_is_dolby_format(out->format))
2653 audio_extn_dolby_send_ddp_endp_params(adev);
2654#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302655 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2656 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002657 if (adev->visualizer_start_output != NULL)
2658 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2659 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302660 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002661 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002662 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002664
2665 if (ret == 0) {
2666 register_out_stream(out);
2667 if (out->realtime) {
2668 ret = pcm_start(out->pcm);
2669 if (ret < 0)
2670 goto error_open;
2671 }
2672 }
2673
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302674 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002675 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002676
Siddartha Shaik15b84ea2017-08-07 12:29:25 +05302677 if (audio_extn_ip_hdlr_intf_supported(out->format, audio_extn_passthru_is_direct_passthrough(out)) && out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07002678 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07002679 if (ret < 0)
2680 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
2681 }
2682
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002683 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002684error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302685 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002687error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302688 /*
2689 * sleep 50ms to allow sufficient time for kernel
2690 * drivers to recover incases like SSR.
2691 */
2692 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002693 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694}
2695
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696static int check_input_parameters(uint32_t sample_rate,
2697 audio_format_t format,
2698 int channel_count)
2699{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002700 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002701
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302702 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2703 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2704 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002705 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302706 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002707
2708 switch (channel_count) {
2709 case 1:
2710 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302711 case 3:
2712 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002713 case 6:
2714 break;
2715 default:
2716 ret = -EINVAL;
2717 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718
2719 switch (sample_rate) {
2720 case 8000:
2721 case 11025:
2722 case 12000:
2723 case 16000:
2724 case 22050:
2725 case 24000:
2726 case 32000:
2727 case 44100:
2728 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302729 case 96000:
2730 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731 break;
2732 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002733 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734 }
2735
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002736 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737}
2738
2739static size_t get_input_buffer_size(uint32_t sample_rate,
2740 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002741 int channel_count,
2742 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743{
2744 size_t size = 0;
2745
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002746 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2747 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002749 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002750 if (is_low_latency)
2751 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302752
2753 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002755 /* make sure the size is multiple of 32 bytes
2756 * At 48 kHz mono 16-bit PCM:
2757 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2758 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2759 */
2760 size += 0x1f;
2761 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002762
2763 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764}
2765
Ashish Jain058165c2016-09-28 23:18:48 +05302766static size_t get_output_period_size(uint32_t sample_rate,
2767 audio_format_t format,
2768 int channel_count,
2769 int duration /*in millisecs*/)
2770{
2771 size_t size = 0;
2772 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2773
2774 if ((duration == 0) || (sample_rate == 0) ||
2775 (bytes_per_sample == 0) || (channel_count == 0)) {
2776 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2777 bytes_per_sample, channel_count);
2778 return -EINVAL;
2779 }
2780
2781 size = (sample_rate *
2782 duration *
2783 bytes_per_sample *
2784 channel_count) / 1000;
2785 /*
2786 * To have same PCM samples for all channels, the buffer size requires to
2787 * be multiple of (number of channels * bytes per sample)
2788 * For writes to succeed, the buffer must be written at address which is multiple of 32
2789 */
2790 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2791
2792 return (size/(channel_count * bytes_per_sample));
2793}
2794
Ashish Jain5106d362016-05-11 19:23:33 +05302795static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2796{
2797 uint64_t actual_frames_rendered = 0;
2798 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2799
2800 /* This adjustment accounts for buffering after app processor.
2801 * It is based on estimated DSP latency per use case, rather than exact.
2802 */
2803 int64_t platform_latency = platform_render_latency(out->usecase) *
2804 out->sample_rate / 1000000LL;
2805
2806 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2807 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2808 * hence only estimate.
2809 */
2810 int64_t signed_frames = out->written - kernel_buffer_size;
2811
2812 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2813
2814 if (signed_frames > 0)
2815 actual_frames_rendered = signed_frames;
2816
2817 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2818 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2819 (long long int)out->written, (int)kernel_buffer_size,
2820 audio_bytes_per_sample(out->compr_config.codec->format),
2821 popcount(out->channel_mask));
2822
2823 return actual_frames_rendered;
2824}
2825
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2827{
2828 struct stream_out *out = (struct stream_out *)stream;
2829
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002830 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831}
2832
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002833static int out_set_sample_rate(struct audio_stream *stream __unused,
2834 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002835{
2836 return -ENOSYS;
2837}
2838
2839static size_t out_get_buffer_size(const struct audio_stream *stream)
2840{
2841 struct stream_out *out = (struct stream_out *)stream;
2842
Naresh Tanniruee3499a2017-01-05 14:05:35 +05302843 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2844 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
2845 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
2846 else
2847 return out->compr_config.fragment_size;
2848 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002849 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07002850 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
2851 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 +05302852 else if (is_offload_usecase(out->usecase) &&
2853 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302854 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002855
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002856 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002857 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002858}
2859
2860static uint32_t out_get_channels(const struct audio_stream *stream)
2861{
2862 struct stream_out *out = (struct stream_out *)stream;
2863
2864 return out->channel_mask;
2865}
2866
2867static audio_format_t out_get_format(const struct audio_stream *stream)
2868{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002869 struct stream_out *out = (struct stream_out *)stream;
2870
2871 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002872}
2873
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002874static int out_set_format(struct audio_stream *stream __unused,
2875 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002876{
2877 return -ENOSYS;
2878}
2879
2880static int out_standby(struct audio_stream *stream)
2881{
2882 struct stream_out *out = (struct stream_out *)stream;
2883 struct audio_device *adev = out->dev;
kunleiza9d11682017-08-04 14:14:09 +08002884 struct audio_usecase *uc_info;
2885 struct listnode *node;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002886
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302887 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2888 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002889
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002890 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002892 if (adev->adm_deregister_stream)
2893 adev->adm_deregister_stream(adev->adm_data, out->handle);
2894
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002895 if (is_offload_usecase(out->usecase))
2896 stop_compressed_output_l(out);
2897
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002898 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002899 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002900 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2901 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302902 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08002903 pthread_mutex_unlock(&adev->lock);
2904 pthread_mutex_unlock(&out->lock);
2905 ALOGD("VOIP output entered standby");
2906 return 0;
2907 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002908 if (out->pcm) {
2909 pcm_close(out->pcm);
2910 out->pcm = NULL;
2911 }
2912 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002913 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302914 out->send_next_track_params = false;
2915 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002916 out->gapless_mdata.encoder_delay = 0;
2917 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002918 if (out->compr != NULL) {
2919 compress_close(out->compr);
2920 out->compr = NULL;
2921 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002922 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002923 stop_output_stream(out);
kunleiza9d11682017-08-04 14:14:09 +08002924 //restore output device for active usecase when current snd device and output device mismatch
2925 list_for_each(node, &adev->usecase_list) {
2926 uc_info = node_to_item(node, struct audio_usecase, list);
2927 if ((uc_info->type == PCM_PLAYBACK) &&
2928 (uc_info->out_snd_device != platform_get_output_snd_device(adev->platform, uc_info->stream.out)))
2929 select_devices(adev, uc_info->id);
2930 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002931 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002932 }
2933 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302934 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002935 return 0;
2936}
2937
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302938static int out_on_error(struct audio_stream *stream)
2939{
2940 struct stream_out *out = (struct stream_out *)stream;
2941 bool do_standby = false;
2942
2943 lock_output_stream(out);
2944 if (!out->standby) {
2945 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2946 stop_compressed_output_l(out);
2947 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2948 } else
2949 do_standby = true;
2950 }
2951 pthread_mutex_unlock(&out->lock);
2952
2953 if (do_standby)
2954 return out_standby(&out->stream.common);
2955
2956 return 0;
2957}
2958
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302959/*
2960 *standby implementation without locks, assumes that the callee already
2961 *has taken adev and out lock.
2962 */
2963int out_standby_l(struct audio_stream *stream)
2964{
2965 struct stream_out *out = (struct stream_out *)stream;
2966 struct audio_device *adev = out->dev;
2967
2968 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2969 stream, out->usecase, use_case_table[out->usecase]);
2970
2971 if (!out->standby) {
2972 if (adev->adm_deregister_stream)
2973 adev->adm_deregister_stream(adev->adm_data, out->handle);
2974
2975 if (is_offload_usecase(out->usecase))
2976 stop_compressed_output_l(out);
2977
2978 out->standby = true;
2979 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2980 voice_extn_compress_voip_close_output_stream(stream);
2981 out->started = 0;
2982 ALOGD("VOIP output entered standby");
2983 return 0;
2984 } else if (!is_offload_usecase(out->usecase)) {
2985 if (out->pcm) {
2986 pcm_close(out->pcm);
2987 out->pcm = NULL;
2988 }
2989 } else {
2990 ALOGD("copl(%p):standby", out);
2991 out->send_next_track_params = false;
2992 out->is_compr_metadata_avail = false;
2993 out->gapless_mdata.encoder_delay = 0;
2994 out->gapless_mdata.encoder_padding = 0;
2995 if (out->compr != NULL) {
2996 compress_close(out->compr);
2997 out->compr = NULL;
2998 }
2999 }
3000 stop_output_stream(out);
3001 }
3002 ALOGD("%s: exit", __func__);
3003 return 0;
3004}
3005
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003006static int out_dump(const struct audio_stream *stream __unused,
3007 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008{
3009 return 0;
3010}
3011
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003012static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3013{
3014 int ret = 0;
3015 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003016
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003017 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003018 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003019 return -EINVAL;
3020 }
3021
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303022 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003023
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003024 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3025 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303026 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003027 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003028 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3029 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303030 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003031 }
3032
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003033 ALOGV("%s new encoder delay %u and padding %u", __func__,
3034 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3035
3036 return 0;
3037}
3038
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003039static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3040{
3041 return out == adev->primary_output || out == adev->voice_tx_output;
3042}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003043
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303044// note: this call is safe only if the stream_cb is
3045// removed first in close_output_stream (as is done now).
3046static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3047{
3048 if (!stream || !parms)
3049 return;
3050
3051 struct stream_out *out = (struct stream_out *)stream;
3052 struct audio_device *adev = out->dev;
3053
3054 card_status_t status;
3055 int card;
3056 if (parse_snd_card_status(parms, &card, &status) < 0)
3057 return;
3058
3059 pthread_mutex_lock(&adev->lock);
3060 bool valid_cb = (card == adev->snd_card);
3061 pthread_mutex_unlock(&adev->lock);
3062
3063 if (!valid_cb)
3064 return;
3065
3066 lock_output_stream(out);
3067 if (out->card_status != status)
3068 out->card_status = status;
3069 pthread_mutex_unlock(&out->lock);
3070
3071 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3072 use_case_table[out->usecase],
3073 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3074
3075 if (status == CARD_STATUS_OFFLINE)
3076 out_on_error(stream);
3077
3078 return;
3079}
3080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3082{
3083 struct stream_out *out = (struct stream_out *)stream;
3084 struct audio_device *adev = out->dev;
3085 struct str_parms *parms;
3086 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003087 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303088 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089
sangwoobc677242013-08-08 16:53:43 +09003090 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003091 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303093 if (!parms)
3094 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003095 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3096 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003098 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003099 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003100
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003101 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003102 * When HDMI cable is unplugged the music playback is paused and
3103 * the policy manager sends routing=0. But the audioflinger continues
3104 * to write data until standby time (3sec). As the HDMI core is
3105 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003106 * Avoid this by routing audio to speaker until standby.
3107 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003108 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3109 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303110 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003111 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3112 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003113 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303114 /*
3115 * When A2DP is disconnected the
3116 * music playback is paused and the policy manager sends routing=0
3117 * But the audioflingercontinues to write data until standby time
3118 * (3sec). As BT is turned off, the write gets blocked.
3119 * Avoid this by routing audio to speaker until standby.
3120 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003121 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303122 (val == AUDIO_DEVICE_NONE)) {
3123 val = AUDIO_DEVICE_OUT_SPEAKER;
3124 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303125 /* To avoid a2dp to sco overlapping / BT device improper state
3126 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303127 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303128 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3129 if (!audio_extn_a2dp_is_ready()) {
3130 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3131 //combo usecase just by pass a2dp
3132 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303133 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303134 } else {
3135 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3136 /* update device to a2dp and don't route as BT returned error
3137 * However it is still possible a2dp routing called because
3138 * of current active device disconnection (like wired headset)
3139 */
3140 out->devices = val;
3141 pthread_mutex_unlock(&out->lock);
3142 pthread_mutex_unlock(&adev->lock);
3143 goto error;
3144 }
3145 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303146 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003147 /*
3148 * select_devices() call below switches all the usecases on the same
3149 * backend to the new device. Refer to check_usecases_codec_backend() in
3150 * the select_devices(). But how do we undo this?
3151 *
3152 * For example, music playback is active on headset (deep-buffer usecase)
3153 * and if we go to ringtones and select a ringtone, low-latency usecase
3154 * will be started on headset+speaker. As we can't enable headset+speaker
3155 * and headset devices at the same time, select_devices() switches the music
3156 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3157 * So when the ringtone playback is completed, how do we undo the same?
3158 *
3159 * We are relying on the out_set_parameters() call on deep-buffer output,
3160 * once the ringtone playback is ended.
3161 * NOTE: We should not check if the current devices are same as new devices.
3162 * Because select_devices() must be called to switch back the music
3163 * playback to headset.
3164 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003165 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003166 audio_devices_t new_dev = val;
3167 bool same_dev = out->devices == new_dev;
3168 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003169
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003170 if (output_drives_call(adev, out)) {
3171 if(!voice_is_in_call(adev)) {
3172 if (adev->mode == AUDIO_MODE_IN_CALL) {
3173 adev->current_call_output = out;
3174 ret = voice_start_call(adev);
3175 }
3176 } else {
3177 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003178 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003179 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003180 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003181
3182 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003183 if (!same_dev) {
3184 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303185 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3186 adev->perf_lock_opts,
3187 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003188 if (adev->adm_on_routing_change)
3189 adev->adm_on_routing_change(adev->adm_data,
3190 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003191 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303192 if (!bypass_a2dp) {
3193 select_devices(adev, out->usecase);
3194 } else {
3195 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3196 select_devices(adev, out->usecase);
3197 out->devices = new_dev;
3198 }
Sudheer Papothi80266982016-08-16 02:36:18 +05303199 if (!same_dev)
3200 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303201 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3202 out->a2dp_compress_mute &&
3203 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP))) {
3204 pthread_mutex_lock(&out->compr_mute_lock);
3205 out->a2dp_compress_mute = false;
3206 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3207 pthread_mutex_unlock(&out->compr_mute_lock);
3208 }
3209
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003210 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003211 }
3212
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003214 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003216
3217 if (out == adev->primary_output) {
3218 pthread_mutex_lock(&adev->lock);
3219 audio_extn_set_parameters(adev, parms);
3220 pthread_mutex_unlock(&adev->lock);
3221 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003222 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003223 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003224 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003225
3226 audio_extn_dts_create_state_notifier_node(out->usecase);
3227 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3228 popcount(out->channel_mask),
3229 out->playback_started);
3230
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003231 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003232 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003233
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303234 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3235 if (err >= 0) {
3236 strlcpy(out->profile, value, sizeof(out->profile));
3237 ALOGV("updating stream profile with value '%s'", out->profile);
3238 lock_output_stream(out);
3239 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3240 &adev->streams_output_cfg_list,
3241 out->devices, out->flags, out->format,
3242 out->sample_rate, out->bit_width,
3243 out->channel_mask, out->profile,
3244 &out->app_type_cfg);
3245 pthread_mutex_unlock(&out->lock);
3246 }
3247
Alexy Joseph98988832017-01-13 14:56:59 -08003248 //suspend, resume handling block
3249 if (out->dynamic_pm_qos_enabled) {
3250 //check suspend parameter only for low latency and if the property
3251 //is enabled
3252 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3253 ALOGI("%s: got suspend_playback %s", __func__, value);
3254 lock_output_stream(out);
3255 if (!strncmp(value, "false", 5)) {
3256 //suspend_playback=false is supposed to set QOS value back to 75%
3257 //the mixer control sent with value Enable will achieve that
3258 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3259 } else if (!strncmp (value, "true", 4)) {
3260 //suspend_playback=true is supposed to remove QOS value
3261 //resetting the mixer control will set the default value
3262 //for the mixer control which is Disable and this removes the QOS vote
3263 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3264 } else {
3265 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3266 " got %s", __func__, value);
3267 ret = -1;
3268 }
3269
3270 if (ret != 0) {
3271 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3272 __func__, out->pm_qos_mixer_path, ret);
3273 }
3274
3275 pthread_mutex_unlock(&out->lock);
3276 }
3277 }
3278 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303280error:
Eric Laurent994a6932013-07-17 11:51:42 -07003281 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003282 return ret;
3283}
3284
3285static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3286{
3287 struct stream_out *out = (struct stream_out *)stream;
3288 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003289 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003290 char value[256];
3291 struct str_parms *reply = str_parms_create();
3292 size_t i, j;
3293 int ret;
3294 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003295
3296 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003297 if (reply) {
3298 str_parms_destroy(reply);
3299 }
3300 if (query) {
3301 str_parms_destroy(query);
3302 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003303 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
3304 return NULL;
3305 }
3306
Eric Laurent994a6932013-07-17 11:51:42 -07003307 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003308 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
3309 if (ret >= 0) {
3310 value[0] = '\0';
3311 i = 0;
3312 while (out->supported_channel_masks[i] != 0) {
3313 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
3314 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
3315 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003316 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003318 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319 first = false;
3320 break;
3321 }
3322 }
3323 i++;
3324 }
3325 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3326 str = str_parms_to_str(reply);
3327 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003328 voice_extn_out_get_parameters(out, query, reply);
3329 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003331
Alexy Joseph62142aa2015-11-16 15:10:34 -08003332
3333 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
3334 if (ret >= 0) {
3335 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05303336 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
3337 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08003338 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303339 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003340 } else {
3341 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05303342 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003343 }
3344 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003345 if (str)
3346 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08003347 str = str_parms_to_str(reply);
3348 }
3349
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003350 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
3351 if (ret >= 0) {
3352 value[0] = '\0';
3353 i = 0;
3354 first = true;
3355 while (out->supported_formats[i] != 0) {
3356 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
3357 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
3358 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003359 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003360 }
3361 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
3362 first = false;
3363 break;
3364 }
3365 }
3366 i++;
3367 }
3368 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003369 if (str)
3370 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003371 str = str_parms_to_str(reply);
3372 }
Mingming Yin3a941d42016-02-17 18:08:05 -08003373
3374 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
3375 if (ret >= 0) {
3376 value[0] = '\0';
3377 i = 0;
3378 first = true;
3379 while (out->supported_sample_rates[i] != 0) {
3380 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
3381 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
3382 if (!first) {
3383 strlcat(value, "|", sizeof(value));
3384 }
3385 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
3386 first = false;
3387 break;
3388 }
3389 }
3390 i++;
3391 }
3392 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
3393 if (str)
3394 free(str);
3395 str = str_parms_to_str(reply);
3396 }
3397
Alexy Joseph98988832017-01-13 14:56:59 -08003398 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
3399 //only low latency track supports suspend_resume
3400 str_parms_add_int(reply, "supports_hw_suspend",
3401 (out->dynamic_pm_qos_enabled));
3402 if (str)
3403 free(str);
3404 str = str_parms_to_str(reply);
3405 }
3406
3407
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408 str_parms_destroy(query);
3409 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003410 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411 return str;
3412}
3413
3414static uint32_t out_get_latency(const struct audio_stream_out *stream)
3415{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003416 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08003418 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419
Alexy Josephaa54c872014-12-03 02:46:47 -08003420 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05303421 lock_output_stream(out);
3422 latency = audio_extn_utils_compress_get_dsp_latency(out);
3423 pthread_mutex_unlock(&out->lock);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003424 } else if (out->realtime) {
3425 // since the buffer won't be filled up faster than realtime,
3426 // return a smaller number
3427 if (out->config.rate)
3428 period_ms = (out->af_period_multiplier * out->config.period_size *
3429 1000) / (out->config.rate);
3430 else
3431 period_ms = 0;
3432 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003433 } else {
3434 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003435 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003436 }
3437
yidongh0515e042017-07-06 15:00:34 +08003438 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003439 latency += audio_extn_a2dp_get_encoder_latency();
3440
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303441 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003442 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003443}
3444
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303445static float AmpToDb(float amplification)
3446{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303447 float db = DSD_VOLUME_MIN_DB;
3448 if (amplification > 0) {
3449 db = 20 * log10(amplification);
3450 if(db < DSD_VOLUME_MIN_DB)
3451 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303452 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303453 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303454}
3455
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303456static int out_set_compr_volume(struct audio_stream_out *stream, float left,
3457 float right)
3458{
3459 struct stream_out *out = (struct stream_out *)stream;
3460 int volume[2];
3461 char mixer_ctl_name[128];
3462 struct audio_device *adev = out->dev;
3463 struct mixer_ctl *ctl;
3464 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3465 PCM_PLAYBACK);
3466
3467 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3468 "Compress Playback %d Volume", pcm_device_id);
3469 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3470 if (!ctl) {
3471 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3472 __func__, mixer_ctl_name);
3473 return -EINVAL;
3474 }
3475 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
3476 __func__, mixer_ctl_name, left, right);
3477 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3478 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3479 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3480
3481 return 0;
3482}
3483
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484static int out_set_volume(struct audio_stream_out *stream, float left,
3485 float right)
3486{
Eric Laurenta9024de2013-04-04 09:19:12 -07003487 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003488 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303489 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003490
Eric Laurenta9024de2013-04-04 09:19:12 -07003491 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3492 /* only take left channel into account: the API is for stereo anyway */
3493 out->muted = (left == 0.0f);
3494 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003495 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303496 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003497 /*
3498 * Set mute or umute on HDMI passthrough stream.
3499 * Only take left channel into account.
3500 * Mute is 0 and unmute 1
3501 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303502 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303503 } else if (out->format == AUDIO_FORMAT_DSD){
3504 char mixer_ctl_name[128] = "DSD Volume";
3505 struct audio_device *adev = out->dev;
3506 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3507
3508 if (!ctl) {
3509 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3510 __func__, mixer_ctl_name);
3511 return -EINVAL;
3512 }
3513 volume[0] = (int)(AmpToDb(left));
3514 volume[1] = (int)(AmpToDb(right));
3515 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3516 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003517 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303518 pthread_mutex_lock(&out->compr_mute_lock);
3519 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3520 if (!out->a2dp_compress_mute)
3521 ret = out_set_compr_volume(stream, left, right);
3522 out->volume_l = left;
3523 out->volume_r = right;
3524 pthread_mutex_unlock(&out->compr_mute_lock);
3525 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003526 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003527 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
3528 char mixer_ctl_name[] = "App Type Gain";
3529 struct audio_device *adev = out->dev;
3530 struct mixer_ctl *ctl;
3531 uint32_t set_values[4];
3532
3533 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3534 if (!ctl) {
3535 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3536 __func__, mixer_ctl_name);
3537 return -EINVAL;
3538 }
3539
3540 set_values[0] = 0; //0: Rx Session 1:Tx Session
3541 set_values[1] = out->app_type_cfg.app_type;
3542 set_values[2] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3543 set_values[3] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3544
3545 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
3546 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003547 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549 return -ENOSYS;
3550}
3551
3552static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3553 size_t bytes)
3554{
3555 struct stream_out *out = (struct stream_out *)stream;
3556 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003557 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003558
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003559 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303560
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303561 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003562
Dhananjay Kumarac341582017-02-23 23:42:25 +05303563 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303564 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303565 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3566 pthread_mutex_unlock(&out->lock);
3567 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303568 } else {
3569 /* increase written size during SSR to avoid mismatch
3570 * with the written frames count in AF
3571 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003572 // bytes per frame
3573 size_t bpf = audio_bytes_per_sample(out->format) *
3574 audio_channel_count_from_out_mask(out->channel_mask);
3575 if (bpf != 0)
3576 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303577 ALOGD(" %s: sound card is not active/SSR state", __func__);
3578 ret= -EIO;
3579 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303580 }
3581 }
3582
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303583 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303584 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ben Romberger4863ed72017-06-23 14:25:27 -07003585 if ((audio_bytes_per_sample(out->format) != 0) && (out->config.channels != 0))
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303586 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3587 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303588 goto exit;
3589 }
3590
Manish Dewangan37864bc2017-06-09 12:28:37 +05303591 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3592 /*ADD audio_extn_passthru_is_passthrough_stream(out) check*/
3593 if ((audio_extn_passthru_is_enabled()) &&
3594 (!out->is_iec61937_info_available)) {
3595 audio_extn_passthru_update_stream_configuration(adev, out,
3596 buffer, bytes);
3597 out->is_iec61937_info_available = true;
3598 }
3599 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303600
3601 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3602 (audio_extn_a2dp_is_suspended())) {
3603 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
3604 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3605 size_t bpf = audio_bytes_per_sample(out->format) *
3606 audio_channel_count_from_out_mask(out->channel_mask);
3607 if (bpf != 0)
3608 out->written += bytes / bpf;
3609 ret = -EIO;
3610 goto exit;
3611 }
3612 }
3613 }
3614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003616 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003617 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003618 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3619 ret = voice_extn_compress_voip_start_output_stream(out);
3620 else
3621 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003622 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003623 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003625 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626 goto exit;
3627 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303628 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003629 if (last_known_cal_step != -1) {
3630 ALOGD("%s: retry previous failed cal level set", __func__);
3631 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05303632 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003633 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635
Ashish Jain81eb2a82015-05-13 10:52:34 +05303636 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003637 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303638 adev->is_channel_status_set = true;
3639 }
3640
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003641 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003642 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003643 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003644 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003645 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3646 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303647 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3648 ALOGD("copl(%p):send next track params in gapless", out);
3649 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3650 out->send_next_track_params = false;
3651 out->is_compr_metadata_avail = false;
3652 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003653 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303654 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303655 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003656
Ashish Jain83a6cc22016-06-28 14:34:17 +05303657 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303658 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303659 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303660 pthread_mutex_unlock(&out->lock);
3661 return -EINVAL;
3662 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303663 audio_format_t dst_format = out->hal_op_format;
3664 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303665
3666 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3667 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3668
Ashish Jain83a6cc22016-06-28 14:34:17 +05303669 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303670 dst_format,
3671 buffer,
3672 src_format,
3673 frames);
3674
Ashish Jain83a6cc22016-06-28 14:34:17 +05303675 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303676 bytes_to_write);
3677
3678 /*Convert written bytes in audio flinger format*/
3679 if (ret > 0)
3680 ret = ((ret * format_to_bitwidth_table[out->format]) /
3681 format_to_bitwidth_table[dst_format]);
3682 }
3683 } else
3684 ret = compress_write(out->compr, buffer, bytes);
3685
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303686 if (ret < 0)
3687 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303688 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303689 /*msg to cb thread only if non blocking write is enabled*/
3690 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303691 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003692 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303693 } else if (-ENETRESET == ret) {
3694 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303695 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05303696 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05303697 out_on_error(&out->stream.common);
Naresh Tanniru80659832014-06-04 18:17:56 +05303698 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003699 }
Ashish Jain5106d362016-05-11 19:23:33 +05303700 if ( ret == (ssize_t)bytes && !out->non_blocking)
3701 out->written += bytes;
3702
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303703 /* Call compr start only when non-zero bytes of data is there to be rendered */
3704 if (!out->playback_started && ret > 0) {
3705 int status = compress_start(out->compr);
3706 if (status < 0) {
3707 ret = status;
3708 ALOGE("%s: compr start failed with err %d", __func__, errno);
3709 goto exit;
3710 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003711 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003712 out->playback_started = 1;
3713 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003714
3715 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3716 popcount(out->channel_mask),
3717 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003718 }
3719 pthread_mutex_unlock(&out->lock);
3720 return ret;
3721 } else {
3722 if (out->pcm) {
3723 if (out->muted)
3724 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003725
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303726 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003727
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003728 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003729
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003730 if (out->config.rate)
3731 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3732 out->config.rate;
3733
3734 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3735
3736 request_out_focus(out, ns);
3737
3738 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003739 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003740 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303741 out->convert_buffer != NULL) {
3742
3743 memcpy_by_audio_format(out->convert_buffer,
3744 out->hal_op_format,
3745 buffer,
3746 out->hal_ip_format,
3747 out->config.period_size * out->config.channels);
3748
3749 ret = pcm_write(out->pcm, out->convert_buffer,
3750 (out->config.period_size *
3751 out->config.channels *
3752 format_to_bitwidth_table[out->hal_op_format]));
3753 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05303754 /*
3755 * To avoid underrun in DSP when the application is not pumping
3756 * data at required rate, check for the no. of bytes and ignore
3757 * pcm_write if it is less than actual buffer size.
3758 * It is a work around to a change in compress VOIP driver.
3759 */
3760 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
3761 bytes < (out->config.period_size * out->config.channels *
3762 audio_bytes_per_sample(out->format))) {
3763 size_t voip_buf_size =
3764 out->config.period_size * out->config.channels *
3765 audio_bytes_per_sample(out->format);
3766 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
3767 __func__, bytes, voip_buf_size);
3768 usleep(((uint64_t)voip_buf_size - bytes) *
3769 1000000 / audio_stream_out_frame_size(stream) /
3770 out_get_sample_rate(&out->stream.common));
3771 ret = 0;
3772 } else
3773 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303774 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003775
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003776 release_out_focus(out);
3777
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303778 if (ret < 0)
3779 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303780 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3781 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3782 else
3783 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003784 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003785 }
3786
3787exit:
Naresh Tanniru4c630392014-05-12 01:05:52 +05303788 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303789 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303790 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003791 pthread_mutex_unlock(&out->lock);
3792
3793 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003794 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003795 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303796 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303797 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303798 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303799 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303800 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303801 out->standby = true;
3802 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303803 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303804 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3805 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3806 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003807 }
3808 return bytes;
3809}
3810
3811static int out_get_render_position(const struct audio_stream_out *stream,
3812 uint32_t *dsp_frames)
3813{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003814 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08003815
3816 if (dsp_frames == NULL)
3817 return -EINVAL;
3818
3819 *dsp_frames = 0;
3820 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003821 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303822
3823 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3824 * this operation and adev_close_output_stream(where out gets reset).
3825 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303826 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303827 *dsp_frames = get_actual_pcm_frames_rendered(out);
3828 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3829 return 0;
3830 }
3831
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003832 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303833 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303834 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003835 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303836 if (ret < 0)
3837 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003838 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303839 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003840 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303841 if (-ENETRESET == ret) {
3842 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303843 out->card_status = CARD_STATUS_OFFLINE;
3844 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303845 } else if(ret < 0) {
3846 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303847 ret = -EINVAL;
3848 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303849 /*
3850 * Handle corner case where compress session is closed during SSR
3851 * and timestamp is queried
3852 */
3853 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303854 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303855 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303856 ret = 0;
Naresh Tanniru80659832014-06-04 18:17:56 +05303857 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303858 pthread_mutex_unlock(&out->lock);
3859 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08003860 } else if (audio_is_linear_pcm(out->format)) {
3861 *dsp_frames = out->written;
3862 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003863 } else
3864 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003865}
3866
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003867static int out_add_audio_effect(const struct audio_stream *stream __unused,
3868 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003869{
3870 return 0;
3871}
3872
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003873static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3874 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003875{
3876 return 0;
3877}
3878
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003879static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3880 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003881{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303882 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003883}
3884
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003885static int out_get_presentation_position(const struct audio_stream_out *stream,
3886 uint64_t *frames, struct timespec *timestamp)
3887{
3888 struct stream_out *out = (struct stream_out *)stream;
3889 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003890 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003891
Ashish Jain5106d362016-05-11 19:23:33 +05303892 /* below piece of code is not guarded against any lock because audioFliner serializes
3893 * this operation and adev_close_output_stream( where out gets reset).
3894 */
3895 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303896 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303897 *frames = get_actual_pcm_frames_rendered(out);
3898 /* this is the best we can do */
3899 clock_gettime(CLOCK_MONOTONIC, timestamp);
3900 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3901 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3902 return 0;
3903 }
3904
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003905 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003906
Ashish Jain5106d362016-05-11 19:23:33 +05303907 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3908 ret = compress_get_tstamp(out->compr, &dsp_frames,
3909 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08003910 // Adjustment accounts for A2dp encoder latency with offload usecases
3911 // Note: Encoder latency is returned in ms.
3912 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3913 unsigned long offset =
3914 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3915 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3916 }
Ashish Jain5106d362016-05-11 19:23:33 +05303917 ALOGVV("%s rendered frames %ld sample_rate %d",
3918 __func__, dsp_frames, out->sample_rate);
3919 *frames = dsp_frames;
3920 if (ret < 0)
3921 ret = -errno;
3922 if (-ENETRESET == ret) {
3923 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303924 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05303925 ret = -EINVAL;
3926 } else
3927 ret = 0;
3928 /* this is the best we can do */
3929 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003930 } else {
3931 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003932 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003933 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3934 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003935 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003936 // This adjustment accounts for buffering after app processor.
3937 // It is based on estimated DSP latency per use case, rather than exact.
3938 signed_frames -=
3939 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3940
Aniket Kumar Lataff613152017-07-18 18:19:21 -07003941 // Adjustment accounts for A2dp encoder latency with non offload usecases
3942 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3943 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3944 signed_frames -=
3945 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3946 }
3947
Eric Laurent949a0892013-09-20 09:20:13 -07003948 // It would be unusual for this value to be negative, but check just in case ...
3949 if (signed_frames >= 0) {
3950 *frames = signed_frames;
3951 ret = 0;
3952 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003953 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303954 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303955 *frames = out->written;
3956 clock_gettime(CLOCK_MONOTONIC, timestamp);
3957 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003958 }
3959 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003960 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003961 return ret;
3962}
3963
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003964static int out_set_callback(struct audio_stream_out *stream,
3965 stream_callback_t callback, void *cookie)
3966{
3967 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003968 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003969
3970 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003971 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003972 out->client_callback = callback;
3973 out->client_cookie = cookie;
3974 if (out->adsp_hdlr_stream_handle) {
3975 ret = audio_extn_adsp_hdlr_stream_set_callback(
3976 out->adsp_hdlr_stream_handle,
3977 callback,
3978 cookie);
3979 if (ret)
3980 ALOGW("%s:adsp hdlr callback registration failed %d",
3981 __func__, ret);
3982 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003983 pthread_mutex_unlock(&out->lock);
3984 return 0;
3985}
3986
3987static int out_pause(struct audio_stream_out* stream)
3988{
3989 struct stream_out *out = (struct stream_out *)stream;
3990 int status = -ENOSYS;
3991 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003992 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003993 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003994 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003995 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303996 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05303997 status = compress_pause(out->compr);
3998
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003999 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004000
Mingming Yin21854652016-04-13 11:54:02 -07004001 if (audio_extn_passthru_is_active()) {
4002 ALOGV("offload use case, pause passthru");
4003 audio_extn_passthru_on_pause(out);
4004 }
4005
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304006 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004007 audio_extn_dts_notify_playback_state(out->usecase, 0,
4008 out->sample_rate, popcount(out->channel_mask),
4009 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004010 }
4011 pthread_mutex_unlock(&out->lock);
4012 }
4013 return status;
4014}
4015
4016static int out_resume(struct audio_stream_out* stream)
4017{
4018 struct stream_out *out = (struct stream_out *)stream;
4019 int status = -ENOSYS;
4020 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004021 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004022 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004023 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004024 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004025 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304026 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304027 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004028 }
4029 if (!status) {
4030 out->offload_state = OFFLOAD_STATE_PLAYING;
4031 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304032 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004033 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4034 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004035 }
4036 pthread_mutex_unlock(&out->lock);
4037 }
4038 return status;
4039}
4040
4041static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
4042{
4043 struct stream_out *out = (struct stream_out *)stream;
4044 int status = -ENOSYS;
4045 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004046 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004047 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004048 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
4049 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
4050 else
4051 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
4052 pthread_mutex_unlock(&out->lock);
4053 }
4054 return status;
4055}
4056
4057static int out_flush(struct audio_stream_out* stream)
4058{
4059 struct stream_out *out = (struct stream_out *)stream;
4060 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004061 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004062 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004063 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004064 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
4065 stop_compressed_output_l(out);
4066 out->written = 0;
4067 } else {
4068 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
4069 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004070 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004071 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004072 return 0;
4073 }
4074 return -ENOSYS;
4075}
4076
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004077/** audio_stream_in implementation **/
4078static uint32_t in_get_sample_rate(const struct audio_stream *stream)
4079{
4080 struct stream_in *in = (struct stream_in *)stream;
4081
4082 return in->config.rate;
4083}
4084
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004085static int in_set_sample_rate(struct audio_stream *stream __unused,
4086 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087{
4088 return -ENOSYS;
4089}
4090
4091static size_t in_get_buffer_size(const struct audio_stream *stream)
4092{
4093 struct stream_in *in = (struct stream_in *)stream;
4094
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004095 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
4096 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004097 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
4098 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 -07004099 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
4100 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304101 else if(audio_extn_cin_attached_usecase(in->usecase))
4102 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004103
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004104 return in->config.period_size * in->af_period_multiplier *
4105 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004106}
4107
4108static uint32_t in_get_channels(const struct audio_stream *stream)
4109{
4110 struct stream_in *in = (struct stream_in *)stream;
4111
4112 return in->channel_mask;
4113}
4114
4115static audio_format_t in_get_format(const struct audio_stream *stream)
4116{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004117 struct stream_in *in = (struct stream_in *)stream;
4118
4119 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004120}
4121
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004122static int in_set_format(struct audio_stream *stream __unused,
4123 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004124{
4125 return -ENOSYS;
4126}
4127
4128static int in_standby(struct audio_stream *stream)
4129{
4130 struct stream_in *in = (struct stream_in *)stream;
4131 struct audio_device *adev = in->dev;
4132 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304133 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4134 stream, in->usecase, use_case_table[in->usecase]);
4135
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004136 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004137 if (!in->standby && in->is_st_session) {
4138 ALOGD("%s: sound trigger pcm stop lab", __func__);
4139 audio_extn_sound_trigger_stop_lab(in);
4140 in->standby = 1;
4141 }
4142
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004143 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004144 if (adev->adm_deregister_stream)
4145 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
4146
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004147 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004148 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004149 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
4150 voice_extn_compress_voip_close_input_stream(stream);
4151 ALOGD("VOIP input entered standby");
4152 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304153 if (audio_extn_cin_attached_usecase(in->usecase))
4154 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08004155 if (in->pcm) {
4156 pcm_close(in->pcm);
4157 in->pcm = NULL;
4158 }
4159 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004160 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004161 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162 }
4163 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07004164 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004165 return status;
4166}
4167
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004168static int in_dump(const struct audio_stream *stream __unused,
4169 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004170{
4171 return 0;
4172}
4173
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304174static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4175{
4176 if (!stream || !parms)
4177 return;
4178
4179 struct stream_in *in = (struct stream_in *)stream;
4180 struct audio_device *adev = in->dev;
4181
4182 card_status_t status;
4183 int card;
4184 if (parse_snd_card_status(parms, &card, &status) < 0)
4185 return;
4186
4187 pthread_mutex_lock(&adev->lock);
4188 bool valid_cb = (card == adev->snd_card);
4189 pthread_mutex_unlock(&adev->lock);
4190
4191 if (!valid_cb)
4192 return;
4193
4194 lock_input_stream(in);
4195 if (in->card_status != status)
4196 in->card_status = status;
4197 pthread_mutex_unlock(&in->lock);
4198
4199 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4200 use_case_table[in->usecase],
4201 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4202
4203 // a better solution would be to report error back to AF and let
4204 // it put the stream to standby
4205 if (status == CARD_STATUS_OFFLINE)
4206 in_standby(&in->stream.common);
4207
4208 return;
4209}
4210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004211static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4212{
4213 struct stream_in *in = (struct stream_in *)stream;
4214 struct audio_device *adev = in->dev;
4215 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004216 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004217 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004218
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304219 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004220 parms = str_parms_create_str(kvpairs);
4221
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304222 if (!parms)
4223 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004224 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004225 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004226
4227 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4228 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004229 val = atoi(value);
4230 /* no audio source uses val == 0 */
4231 if ((in->source != val) && (val != 0)) {
4232 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004233 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4234 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4235 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004236 (in->config.rate == 8000 || in->config.rate == 16000 ||
4237 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004238 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004239 err = voice_extn_compress_voip_open_input_stream(in);
4240 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004241 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004242 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004243 }
4244 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245 }
4246 }
4247
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004248 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4249 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004250 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004251 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004252 in->device = val;
4253 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004254 if (!in->standby && !in->is_st_session) {
4255 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07004256 if (adev->adm_on_routing_change)
4257 adev->adm_on_routing_change(adev->adm_data,
4258 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004259 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004260 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004261 }
4262 }
4263
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304264 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4265 if (err >= 0) {
4266 strlcpy(in->profile, value, sizeof(in->profile));
4267 ALOGV("updating stream profile with value '%s'", in->profile);
4268 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4269 &adev->streams_input_cfg_list,
4270 in->device, in->flags, in->format,
4271 in->sample_rate, in->bit_width,
4272 in->profile, &in->app_type_cfg);
4273 }
4274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004275 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004276 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004277
4278 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304279error:
Eric Laurent994a6932013-07-17 11:51:42 -07004280 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004281 return ret;
4282}
4283
4284static char* in_get_parameters(const struct audio_stream *stream,
4285 const char *keys)
4286{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004287 struct stream_in *in = (struct stream_in *)stream;
4288 struct str_parms *query = str_parms_create_str(keys);
4289 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004290 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004291
4292 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004293 if (reply) {
4294 str_parms_destroy(reply);
4295 }
4296 if (query) {
4297 str_parms_destroy(query);
4298 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004299 ALOGE("in_get_parameters: failed to create query or reply");
4300 return NULL;
4301 }
4302
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004303 ALOGV("%s: enter: keys - %s", __func__, keys);
4304
4305 voice_extn_in_get_parameters(in, query, reply);
4306
4307 str = str_parms_to_str(reply);
4308 str_parms_destroy(query);
4309 str_parms_destroy(reply);
4310
4311 ALOGV("%s: exit: returns - %s", __func__, str);
4312 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313}
4314
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004315static int in_set_gain(struct audio_stream_in *stream __unused,
4316 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004317{
4318 return 0;
4319}
4320
4321static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4322 size_t bytes)
4323{
4324 struct stream_in *in = (struct stream_in *)stream;
4325 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304326 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304327 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004328
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004329 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304330
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004331 if (in->is_st_session) {
4332 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
4333 /* Read from sound trigger HAL */
4334 audio_extn_sound_trigger_read(in, buffer, bytes);
4335 pthread_mutex_unlock(&in->lock);
4336 return bytes;
4337 }
4338
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004339 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004340 pthread_mutex_lock(&adev->lock);
4341 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
4342 ret = voice_extn_compress_voip_start_input_stream(in);
4343 else
4344 ret = start_input_stream(in);
4345 pthread_mutex_unlock(&adev->lock);
4346 if (ret != 0) {
4347 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004348 }
4349 in->standby = 0;
4350 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004351
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004352 // what's the duration requested by the client?
4353 long ns = 0;
4354
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304355 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004356 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4357 in->config.rate;
4358
4359 request_in_focus(in, ns);
4360 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004361
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304362 if (audio_extn_cin_attached_usecase(in->usecase)) {
4363 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
4364 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304365 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004366 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304367 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07004368 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004369 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004370 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304371 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004372 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304373 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4374 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4375 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
4376 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304377 ret = -EINVAL;
4378 goto exit;
4379 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304380 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304381 ret = -errno;
4382 }
4383 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304384 /* bytes read is always set to bytes for non compress usecases */
4385 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004386 }
4387
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004388 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390 /*
4391 * Instead of writing zeroes here, we could trust the hardware
4392 * to always provide zeroes when muted.
4393 */
Pavan Chikkala63964842014-12-04 10:48:28 +05304394 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
4395 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004396 memset(buffer, 0, bytes);
4397
4398exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004399 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304400 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004401 pthread_mutex_unlock(&in->lock);
4402
4403 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304404 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304405 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304406 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304407 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304408 in->standby = true;
4409 }
Sharad Sangled17c9122017-03-20 15:58:52 +05304410 if (!audio_extn_cin_attached_usecase(in->usecase)) {
4411 bytes_read = bytes;
4412 memset(buffer, 0, bytes);
4413 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004414 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004415 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05304416 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05304417 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004418 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304419 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420}
4421
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004422static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423{
4424 return 0;
4425}
4426
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004427static int add_remove_audio_effect(const struct audio_stream *stream,
4428 effect_handle_t effect,
4429 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004430{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004431 struct stream_in *in = (struct stream_in *)stream;
4432 int status = 0;
4433 effect_descriptor_t desc;
4434
4435 status = (*effect)->get_descriptor(effect, &desc);
4436 if (status != 0)
4437 return status;
4438
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004439 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004440 pthread_mutex_lock(&in->dev->lock);
4441 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4442 in->enable_aec != enable &&
4443 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4444 in->enable_aec = enable;
4445 if (!in->standby)
4446 select_devices(in->dev, in->usecase);
4447 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08004448 if (in->enable_ns != enable &&
4449 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4450 in->enable_ns = enable;
4451 if (!in->standby)
4452 select_devices(in->dev, in->usecase);
4453 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004454 pthread_mutex_unlock(&in->dev->lock);
4455 pthread_mutex_unlock(&in->lock);
4456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004457 return 0;
4458}
4459
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004460static int in_add_audio_effect(const struct audio_stream *stream,
4461 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004462{
Eric Laurent994a6932013-07-17 11:51:42 -07004463 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004464 return add_remove_audio_effect(stream, effect, true);
4465}
4466
4467static int in_remove_audio_effect(const struct audio_stream *stream,
4468 effect_handle_t effect)
4469{
Eric Laurent994a6932013-07-17 11:51:42 -07004470 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004471 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004472}
4473
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304474int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004475 audio_io_handle_t handle,
4476 audio_devices_t devices,
4477 audio_output_flags_t flags,
4478 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004479 struct audio_stream_out **stream_out,
4480 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004481{
4482 struct audio_device *adev = (struct audio_device *)dev;
4483 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304484 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004485 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004486 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004488 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304489
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004490 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4491
Mingming Yin3a941d42016-02-17 18:08:05 -08004492 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
4493 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304494 devices, flags, &out->stream);
4495
4496
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004497 if (!out) {
4498 return -ENOMEM;
4499 }
4500
Haynes Mathew George204045b2015-02-25 20:32:03 -08004501 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004502 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304503 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08004504 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004506 if (devices == AUDIO_DEVICE_NONE)
4507 devices = AUDIO_DEVICE_OUT_SPEAKER;
4508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004509 out->flags = flags;
4510 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004511 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004512 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004513 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05304514 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05304515 if (out->channel_mask == AUDIO_CHANNEL_NONE)
4516 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
4517 else
4518 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07004519 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004520 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08004521 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304522 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304523 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304524 out->a2dp_compress_mute = false;
Alexy Joseph98988832017-01-13 14:56:59 -08004525 out->dynamic_pm_qos_enabled = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004526
Mingming Yin3a941d42016-02-17 18:08:05 -08004527 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4528 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
4529 pthread_mutex_lock(&adev->lock);
4530 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
4531 ret = read_hdmi_sink_caps(out);
4532 pthread_mutex_unlock(&adev->lock);
4533 if (ret != 0) {
4534 if (ret == -ENOSYS) {
4535 /* ignore and go with default */
4536 ret = 0;
4537 } else {
4538 ALOGE("error reading hdmi sink caps");
4539 goto error_open;
4540 }
4541 }
4542 }
4543
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004544 /* Init use case and pcm_config */
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004545#ifndef COMPRESS_VOIP_ENABLED
4546 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4547 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
4548 out->sample_rate == 32000 || out->sample_rate == 48000)) {
4549 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
4550 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
4551 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4552
4553 out->config = default_pcm_config_voip_copp;
4554 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
4555 out->config.rate = out->sample_rate;
4556
4557#else
Dhananjay Kumarac341582017-02-23 23:42:25 +05304558 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004559 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08004560 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004561 ret = voice_extn_compress_voip_open_output_stream(out);
4562 if (ret != 0) {
4563 ALOGE("%s: Compress voip output cannot be opened, error:%d",
4564 __func__, ret);
4565 goto error_open;
4566 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004567#endif
vivek mehta0ea887a2015-08-26 14:01:20 -07004568 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304569 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304570 pthread_mutex_lock(&adev->lock);
4571 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4572 pthread_mutex_unlock(&adev->lock);
4573
4574 // reject offload during card offline to allow
4575 // fallback to s/w paths
4576 if (offline) {
4577 ret = -ENODEV;
4578 goto error_open;
4579 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004580
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004581 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4582 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4583 ALOGE("%s: Unsupported Offload information", __func__);
4584 ret = -EINVAL;
4585 goto error_open;
4586 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004587
Mingming Yin3a941d42016-02-17 18:08:05 -08004588 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004589 if(config->offload_info.format == 0)
4590 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004591 if (config->offload_info.sample_rate == 0)
4592 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004593 }
4594
Mingming Yin90310102013-11-13 16:57:00 -08004595 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304596 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004597 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004598 ret = -EINVAL;
4599 goto error_open;
4600 }
4601
Ben Romberger0f8c87b2017-05-24 17:41:11 -07004602 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
4603 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
4604 (audio_extn_passthru_is_passthrough_stream(out)) &&
4605 !((config->sample_rate == 48000) ||
4606 (config->sample_rate == 96000) ||
4607 (config->sample_rate == 192000))) {
4608 ALOGE("%s: Unsupported sample rate %d for audio format %x",
4609 __func__, config->sample_rate, config->offload_info.format);
4610 ret = -EINVAL;
4611 goto error_open;
4612 }
4613
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004614 out->compr_config.codec = (struct snd_codec *)
4615 calloc(1, sizeof(struct snd_codec));
4616
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004617 if (!out->compr_config.codec) {
4618 ret = -ENOMEM;
4619 goto error_open;
4620 }
4621
Dhananjay Kumarac341582017-02-23 23:42:25 +05304622 out->stream.pause = out_pause;
4623 out->stream.resume = out_resume;
4624 out->stream.flush = out_flush;
4625 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004626 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004627 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304628 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004629 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304630 } else {
4631 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4632 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004633 }
vivek mehta446c3962015-09-14 10:57:35 -07004634
4635 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004636 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4637 config->format == 0 && config->sample_rate == 0 &&
4638 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004639 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004640 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4641 } else {
4642 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4643 ret = -EEXIST;
4644 goto error_open;
4645 }
vivek mehta446c3962015-09-14 10:57:35 -07004646 }
4647
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004648 if (config->offload_info.channel_mask)
4649 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004650 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004651 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004652 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004653 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304654 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004655 ret = -EINVAL;
4656 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004657 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004658
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004659 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004660 out->sample_rate = config->offload_info.sample_rate;
4661
Mingming Yin3ee55c62014-08-04 14:23:35 -07004662 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004663
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304664 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4665 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4666 audio_extn_dolby_send_ddp_endp_params(adev);
4667 audio_extn_dolby_set_dmid(adev);
4668 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004669
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004670 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004671 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004672 out->compr_config.codec->bit_rate =
4673 config->offload_info.bit_rate;
4674 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304675 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004676 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304677 /* Update bit width only for non passthrough usecases.
4678 * For passthrough usecases, the output will always be opened @16 bit
4679 */
4680 if (!audio_extn_passthru_is_passthrough_stream(out))
4681 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304682
4683 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4684 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
4685 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
4686
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004687 /*TODO: Do we need to change it for passthrough */
4688 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004689
Manish Dewangana6fc5442015-08-24 20:30:31 +05304690 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4691 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304692 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304693 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304694 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4695 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304696
4697 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4698 AUDIO_FORMAT_PCM) {
4699
4700 /*Based on platform support, configure appropriate alsa format for corresponding
4701 *hal input format.
4702 */
4703 out->compr_config.codec->format = hal_format_to_alsa(
4704 config->offload_info.format);
4705
Ashish Jain83a6cc22016-06-28 14:34:17 +05304706 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304707 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304708 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304709
Dhananjay Kumarac341582017-02-23 23:42:25 +05304710 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304711 *hal input format and alsa format might differ based on platform support.
4712 */
4713 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304714 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304715
4716 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4717
4718 /* Check if alsa session is configured with the same format as HAL input format,
4719 * if not then derive correct fragment size needed to accomodate the
4720 * conversion of HAL input format to alsa format.
4721 */
4722 audio_extn_utils_update_direct_pcm_fragment_size(out);
4723
4724 /*if hal input and output fragment size is different this indicates HAL input format is
4725 *not same as the alsa format
4726 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304727 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304728 /*Allocate a buffer to convert input data to the alsa configured format.
4729 *size of convert buffer is equal to the size required to hold one fragment size
4730 *worth of pcm data, this is because flinger does not write more than fragment_size
4731 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304732 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4733 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304734 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4735 ret = -ENOMEM;
4736 goto error_open;
4737 }
4738 }
4739 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4740 out->compr_config.fragment_size =
4741 audio_extn_passthru_get_buffer_size(&config->offload_info);
4742 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4743 } else {
4744 out->compr_config.fragment_size =
4745 platform_get_compress_offload_buffer_size(&config->offload_info);
4746 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4747 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004748
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304749 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4750 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
4751 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07004752 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304753 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004754
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304755 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4756 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4757 }
4758
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004759 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4760 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004761
Manish Dewangan69426c82017-01-30 17:35:36 +05304762 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
4763 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
4764 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
4765 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4766 out->render_mode = RENDER_MODE_AUDIO_MASTER;
4767 } else {
4768 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
4769 }
Alexy Josephaa54c872014-12-03 02:46:47 -08004770
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05304771 memset(&out->channel_map_param, 0,
4772 sizeof(struct audio_out_channel_map_param));
4773
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004774 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304775 out->send_next_track_params = false;
4776 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004777 out->offload_state = OFFLOAD_STATE_IDLE;
4778 out->playback_started = 0;
4779
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004780 audio_extn_dts_create_state_notifier_node(out->usecase);
4781
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004782 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4783 __func__, config->offload_info.version,
4784 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304785
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304786 /* Check if DSD audio format is supported in codec
4787 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304788 */
4789
4790 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304791 (!platform_check_codec_dsd_support(adev->platform) ||
4792 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304793 ret = -EINVAL;
4794 goto error_open;
4795 }
4796
Ashish Jain5106d362016-05-11 19:23:33 +05304797 /* Disable gapless if any of the following is true
4798 * passthrough playback
4799 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304800 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304801 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304802 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304803 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07004804 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304805 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304806 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304807 check_and_set_gapless_mode(adev, false);
4808 } else
4809 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004810
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304811 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004812 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4813 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304814 if (config->format == AUDIO_FORMAT_DSD) {
4815 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4816 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4817 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004818
4819 create_offload_callback_thread(out);
4820
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004821 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304822 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004823 if (ret != 0) {
4824 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4825 __func__, ret);
4826 goto error_open;
4827 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004828 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4829 if (config->sample_rate == 0)
4830 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4831 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4832 config->sample_rate != 8000) {
4833 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4834 ret = -EINVAL;
4835 goto error_open;
4836 }
4837 out->sample_rate = config->sample_rate;
4838 out->config.rate = config->sample_rate;
4839 if (config->format == AUDIO_FORMAT_DEFAULT)
4840 config->format = AUDIO_FORMAT_PCM_16_BIT;
4841 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4842 config->format = AUDIO_FORMAT_PCM_16_BIT;
4843 ret = -EINVAL;
4844 goto error_open;
4845 }
4846 out->format = config->format;
4847 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4848 out->config = pcm_config_afe_proxy_playback;
4849 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004850 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304851 unsigned int channels = 0;
4852 /*Update config params to default if not set by the caller*/
4853 if (config->sample_rate == 0)
4854 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4855 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4856 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4857 if (config->format == AUDIO_FORMAT_DEFAULT)
4858 config->format = AUDIO_FORMAT_PCM_16_BIT;
4859
4860 channels = audio_channel_count_from_out_mask(out->channel_mask);
4861
Ashish Jain83a6cc22016-06-28 14:34:17 +05304862 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4863 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004864 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4865 out->flags);
4866 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304867 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4868 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Alexy Joseph98988832017-01-13 14:56:59 -08004869 out->dynamic_pm_qos_enabled = property_get_bool("vendor.audio.dynamic.qos.enable", false);
4870 if (!out->dynamic_pm_qos_enabled) {
4871 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
4872 } else {
4873 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
4874 //the mixer path will be a string similar to "low-latency-playback resume"
4875 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
4876 strlcat(out->pm_qos_mixer_path,
4877 " resume", MAX_MIXER_PATH_LEN);
4878 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
4879 out->pm_qos_mixer_path);
4880 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304881 out->config = pcm_config_low_latency;
4882 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4883 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4884 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304885 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4886 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4887 if (out->config.period_size <= 0) {
4888 ALOGE("Invalid configuration period size is not valid");
4889 ret = -EINVAL;
4890 goto error_open;
4891 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304892 } else {
4893 /* primary path is the default path selected if no other outputs are available/suitable */
4894 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4895 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4896 }
4897 out->hal_ip_format = format = out->format;
4898 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4899 out->hal_op_format = pcm_format_to_hal(out->config.format);
4900 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4901 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004902 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304903 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304904 if (out->hal_ip_format != out->hal_op_format) {
4905 uint32_t buffer_size = out->config.period_size *
4906 format_to_bitwidth_table[out->hal_op_format] *
4907 out->config.channels;
4908 out->convert_buffer = calloc(1, buffer_size);
4909 if (out->convert_buffer == NULL){
4910 ALOGE("Allocation failed for convert buffer for size %d",
4911 out->compr_config.fragment_size);
4912 ret = -ENOMEM;
4913 goto error_open;
4914 }
4915 ALOGD("Convert buffer allocated of size %d", buffer_size);
4916 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004917 }
4918
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004919 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4920 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304921
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004922 /* TODO remove this hardcoding and check why width is zero*/
4923 if (out->bit_width == 0)
4924 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304925 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004926 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304927 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304928 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304929 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004930 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4931 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4932 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004933 if(adev->primary_output == NULL)
4934 adev->primary_output = out;
4935 else {
4936 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004937 ret = -EEXIST;
4938 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004939 }
4940 }
4941
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004942 /* Check if this usecase is already existing */
4943 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004944 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4945 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004946 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004947 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004948 ret = -EEXIST;
4949 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004950 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004952 pthread_mutex_unlock(&adev->lock);
4953
4954 out->stream.common.get_sample_rate = out_get_sample_rate;
4955 out->stream.common.set_sample_rate = out_set_sample_rate;
4956 out->stream.common.get_buffer_size = out_get_buffer_size;
4957 out->stream.common.get_channels = out_get_channels;
4958 out->stream.common.get_format = out_get_format;
4959 out->stream.common.set_format = out_set_format;
4960 out->stream.common.standby = out_standby;
4961 out->stream.common.dump = out_dump;
4962 out->stream.common.set_parameters = out_set_parameters;
4963 out->stream.common.get_parameters = out_get_parameters;
4964 out->stream.common.add_audio_effect = out_add_audio_effect;
4965 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4966 out->stream.get_latency = out_get_latency;
4967 out->stream.set_volume = out_set_volume;
4968 out->stream.write = out_write;
4969 out->stream.get_render_position = out_get_render_position;
4970 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004971 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004972
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004973 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004974 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004975 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004976 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004977
4978 config->format = out->stream.common.get_format(&out->stream.common);
4979 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4980 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4981
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304982 /*
4983 By locking output stream before registering, we allow the callback
4984 to update stream's state only after stream's initial state is set to
4985 adev state.
4986 */
4987 lock_output_stream(out);
4988 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4989 pthread_mutex_lock(&adev->lock);
4990 out->card_status = adev->card_status;
4991 pthread_mutex_unlock(&adev->lock);
4992 pthread_mutex_unlock(&out->lock);
4993
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004994 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304995 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004996 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004997
4998 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4999 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5000 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005001 /* setup a channel for client <--> adsp communication for stream events */
5002 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07005003 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Siddartha Shaik15b84ea2017-08-07 12:29:25 +05305004 (audio_extn_ip_hdlr_intf_supported(config->format, audio_extn_passthru_is_direct_passthrough(out)))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005005 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
5006 out->usecase, PCM_PLAYBACK);
5007 hdlr_stream_cfg.flags = out->flags;
5008 hdlr_stream_cfg.type = PCM_PLAYBACK;
5009 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
5010 &hdlr_stream_cfg);
5011 if (ret) {
5012 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
5013 out->adsp_hdlr_stream_handle = NULL;
5014 }
5015 }
Siddartha Shaik15b84ea2017-08-07 12:29:25 +05305016 if (audio_extn_ip_hdlr_intf_supported(config->format, audio_extn_passthru_is_direct_passthrough(out))) {
Naresh Tanniru85819452017-05-04 18:55:45 -07005017 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL);
5018 if (ret < 0) {
5019 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
5020 out->ip_hdlr_handle = NULL;
5021 }
5022 }
Eric Laurent994a6932013-07-17 11:51:42 -07005023 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005024 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005025
5026error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05305027 if (out->convert_buffer)
5028 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005029 free(out);
5030 *stream_out = NULL;
5031 ALOGD("%s: exit: ret %d", __func__, ret);
5032 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005033}
5034
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305035void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005036 struct audio_stream_out *stream)
5037{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005038 struct stream_out *out = (struct stream_out *)stream;
5039 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005040 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005041
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305042 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
5043
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305044 // must deregister from sndmonitor first to prevent races
5045 // between the callback and close_stream
5046 audio_extn_snd_mon_unregister_listener(out);
5047
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005048 /* close adsp hdrl session before standby */
5049 if (out->adsp_hdlr_stream_handle) {
5050 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
5051 if (ret)
5052 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
5053 out->adsp_hdlr_stream_handle = NULL;
5054 }
5055
Siddartha Shaik15b84ea2017-08-07 12:29:25 +05305056 if (audio_extn_ip_hdlr_intf_supported(out->format, audio_extn_passthru_is_direct_passthrough(out)) && out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07005057 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
5058 out->ip_hdlr_handle = NULL;
5059 }
5060
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005061 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305062 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005063 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305064 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305065 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005066 if(ret != 0)
5067 ALOGE("%s: Compress voip output cannot be closed, error:%d",
5068 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005069 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005070 out_standby(&stream->common);
5071
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005072 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005073 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005074 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005075 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005076 if (out->compr_config.codec != NULL)
5077 free(out->compr_config.codec);
5078 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005079
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305080 out->a2dp_compress_mute = false;
5081
Ashish Jain83a6cc22016-06-28 14:34:17 +05305082 if (out->convert_buffer != NULL) {
5083 free(out->convert_buffer);
5084 out->convert_buffer = NULL;
5085 }
5086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005087 if (adev->voice_tx_output == out)
5088 adev->voice_tx_output = NULL;
5089
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05305090 if (adev->primary_output == out)
5091 adev->primary_output = NULL;
5092
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005093 pthread_cond_destroy(&out->cond);
5094 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005095 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005096 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005097}
5098
5099static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5100{
5101 struct audio_device *adev = (struct audio_device *)dev;
5102 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005103 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005104 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005105 int ret;
5106 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005107
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005108 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005109 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005110
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305111 if (!parms)
5112 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305113
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305114 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
5115 if (ret >= 0) {
5116 /* When set to false, HAL should disable EC and NS */
5117 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5118 adev->bt_sco_on = true;
5119 else
5120 adev->bt_sco_on = false;
5121 }
5122
Naresh Tanniru4c630392014-05-12 01:05:52 +05305123 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005124 status = voice_set_parameters(adev, parms);
5125 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005126 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005127
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005128 status = platform_set_parameters(adev->platform, parms);
5129 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005130 goto done;
5131
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005132 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5133 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07005134 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005135 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5136 adev->bluetooth_nrec = true;
5137 else
5138 adev->bluetooth_nrec = false;
5139 }
5140
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005141 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5142 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005143 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5144 adev->screen_off = false;
5145 else
5146 adev->screen_off = true;
5147 }
5148
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005149 ret = str_parms_get_int(parms, "rotation", &val);
5150 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005151 bool reverse_speakers = false;
5152 switch(val) {
5153 // FIXME: note that the code below assumes that the speakers are in the correct placement
5154 // relative to the user when the device is rotated 90deg from its default rotation. This
5155 // assumption is device-specific, not platform-specific like this code.
5156 case 270:
5157 reverse_speakers = true;
5158 break;
5159 case 0:
5160 case 90:
5161 case 180:
5162 break;
5163 default:
5164 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005165 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005166 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005167 if (status == 0) {
5168 if (adev->speaker_lr_swap != reverse_speakers) {
5169 adev->speaker_lr_swap = reverse_speakers;
5170 // only update the selected device if there is active pcm playback
5171 struct audio_usecase *usecase;
5172 struct listnode *node;
5173 list_for_each(node, &adev->usecase_list) {
5174 usecase = node_to_item(node, struct audio_usecase, list);
5175 if (usecase->type == PCM_PLAYBACK) {
5176 select_devices(adev, usecase->id);
5177 break;
5178 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005179 }
5180 }
5181 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005182 }
5183
Mingming Yin514a8bc2014-07-29 15:22:21 -07005184 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5185 if (ret >= 0) {
5186 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5187 adev->bt_wb_speech_enabled = true;
5188 else
5189 adev->bt_wb_speech_enabled = false;
5190 }
5191
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005192 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5193 if (ret >= 0) {
5194 val = atoi(value);
5195 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005196 ALOGV("cache new ext disp type and edid");
5197 ret = platform_get_ext_disp_type(adev->platform);
5198 if (ret < 0) {
5199 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08005200 status = ret;
5201 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005202 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005203 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005204 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005205 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07005206 /*
5207 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
5208 * Per AudioPolicyManager, USB device is higher priority than WFD.
5209 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
5210 * If WFD use case occupies AFE proxy, it may result unintended behavior while
5211 * starting voice call on USB
5212 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005213 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5214 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08005215 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5216 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005217 }
vivek mehta344576a2016-04-12 18:56:03 -07005218 ALOGV("detected USB connect .. disable proxy");
5219 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005220 }
5221 }
5222
5223 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5224 if (ret >= 0) {
5225 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07005226 /*
5227 * The HDMI / Displayport disconnect handling has been moved to
5228 * audio extension to ensure that its parameters are not
5229 * invalidated prior to updating sysfs of the disconnect event
5230 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
5231 */
5232 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005233 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005234 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5235 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05305236 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5237 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005238 }
vivek mehta344576a2016-04-12 18:56:03 -07005239 ALOGV("detected USB disconnect .. enable proxy");
5240 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005241 }
5242 }
5243
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305244 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
5245 if (ret >= 0) {
5246 struct audio_usecase *usecase;
5247 struct listnode *node;
5248 list_for_each(node, &adev->usecase_list) {
5249 usecase = node_to_item(node, struct audio_usecase, list);
5250 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07005251 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305252 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08005253
5254 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305255 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08005256 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305257 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305258 //force device switch to re configure encoder
5259 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305260 audio_extn_a2dp_set_handoff_mode(false);
5261 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305262 break;
5263 }
5264 }
5265 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005266
5267 //handle vr audio setparam
5268 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5269 value, sizeof(value));
5270 if (ret >= 0) {
5271 ALOGI("Setting vr mode to be %s", value);
5272 if (!strncmp(value, "true", 4)) {
5273 adev->vr_audio_mode_enabled = true;
5274 ALOGI("Setting vr mode to true");
5275 } else if (!strncmp(value, "false", 5)) {
5276 adev->vr_audio_mode_enabled = false;
5277 ALOGI("Setting vr mode to false");
5278 } else {
5279 ALOGI("wrong vr mode set");
5280 }
5281 }
5282
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305283 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005284done:
5285 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005286 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305287error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005288 ALOGV("%s: exit with code(%d)", __func__, status);
5289 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005290}
5291
5292static char* adev_get_parameters(const struct audio_hw_device *dev,
5293 const char *keys)
5294{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005295 struct audio_device *adev = (struct audio_device *)dev;
5296 struct str_parms *reply = str_parms_create();
5297 struct str_parms *query = str_parms_create_str(keys);
5298 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05305299 char value[256] = {0};
5300 int ret = 0;
5301
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005302 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005303 if (reply) {
5304 str_parms_destroy(reply);
5305 }
5306 if (query) {
5307 str_parms_destroy(query);
5308 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005309 ALOGE("adev_get_parameters: failed to create query or reply");
5310 return NULL;
5311 }
5312
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005313 //handle vr audio getparam
5314
5315 ret = str_parms_get_str(query,
5316 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5317 value, sizeof(value));
5318
5319 if (ret >= 0) {
5320 bool vr_audio_enabled = false;
5321 pthread_mutex_lock(&adev->lock);
5322 vr_audio_enabled = adev->vr_audio_mode_enabled;
5323 pthread_mutex_unlock(&adev->lock);
5324
5325 ALOGI("getting vr mode to %d", vr_audio_enabled);
5326
5327 if (vr_audio_enabled) {
5328 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5329 "true");
5330 goto exit;
5331 } else {
5332 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5333 "false");
5334 goto exit;
5335 }
5336 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005337
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005338 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005339 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08005340 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005341 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05305342 pthread_mutex_unlock(&adev->lock);
5343
Naresh Tannirud7205b62014-06-20 02:54:48 +05305344exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005345 str = str_parms_to_str(reply);
5346 str_parms_destroy(query);
5347 str_parms_destroy(reply);
5348
5349 ALOGV("%s: exit: returns - %s", __func__, str);
5350 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005351}
5352
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005353static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005354{
5355 return 0;
5356}
5357
5358static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5359{
Haynes Mathew George5191a852013-09-11 14:19:36 -07005360 int ret;
5361 struct audio_device *adev = (struct audio_device *)dev;
5362 pthread_mutex_lock(&adev->lock);
5363 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07005364 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005365 pthread_mutex_unlock(&adev->lock);
5366 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005367}
5368
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005369static int adev_set_master_volume(struct audio_hw_device *dev __unused,
5370 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005371{
5372 return -ENOSYS;
5373}
5374
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005375static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5376 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005377{
5378 return -ENOSYS;
5379}
5380
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005381static int adev_set_master_mute(struct audio_hw_device *dev __unused,
5382 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005383{
5384 return -ENOSYS;
5385}
5386
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005387static int adev_get_master_mute(struct audio_hw_device *dev __unused,
5388 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005389{
5390 return -ENOSYS;
5391}
5392
5393static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5394{
5395 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005397 pthread_mutex_lock(&adev->lock);
5398 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005399 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005400 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08005401 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005402 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07005403 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005404 adev->current_call_output = NULL;
5405 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005406 }
5407 pthread_mutex_unlock(&adev->lock);
5408 return 0;
5409}
5410
5411static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5412{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005413 int ret;
5414
5415 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08005416 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005417 ret = voice_set_mic_mute((struct audio_device *)dev, state);
5418 pthread_mutex_unlock(&adev->lock);
5419
5420 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005421}
5422
5423static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5424{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005425 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005426 return 0;
5427}
5428
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005429static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005430 const struct audio_config *config)
5431{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005432 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005433
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005434 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
5435 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005436}
5437
5438static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005439 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005440 audio_devices_t devices,
5441 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005442 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305443 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005444 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005445 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005446{
5447 struct audio_device *adev = (struct audio_device *)dev;
5448 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005449 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005450 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005451 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305452 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005454 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305455 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
5456 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005457 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305458 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005459
5460 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005461
5462 if (!in) {
5463 ALOGE("failed to allocate input stream");
5464 return -ENOMEM;
5465 }
5466
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305467 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305468 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
5469 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005470 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005471 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005472
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005473 in->stream.common.get_sample_rate = in_get_sample_rate;
5474 in->stream.common.set_sample_rate = in_set_sample_rate;
5475 in->stream.common.get_buffer_size = in_get_buffer_size;
5476 in->stream.common.get_channels = in_get_channels;
5477 in->stream.common.get_format = in_get_format;
5478 in->stream.common.set_format = in_set_format;
5479 in->stream.common.standby = in_standby;
5480 in->stream.common.dump = in_dump;
5481 in->stream.common.set_parameters = in_set_parameters;
5482 in->stream.common.get_parameters = in_get_parameters;
5483 in->stream.common.add_audio_effect = in_add_audio_effect;
5484 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5485 in->stream.set_gain = in_set_gain;
5486 in->stream.read = in_read;
5487 in->stream.get_input_frames_lost = in_get_input_frames_lost;
5488
5489 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005490 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005491 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005492 in->standby = 1;
5493 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005494 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005495 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005496
Dhananjay Kumar973fc362017-01-09 18:48:15 +05305497 in->usecase = USECASE_AUDIO_RECORD;
5498 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
5499 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
5500 is_low_latency = true;
5501#if LOW_LATENCY_CAPTURE_USE_CASE
5502 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
5503#endif
5504 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
5505 }
5506
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005507 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005508 if (in->realtime) {
5509 in->config = pcm_config_audio_capture_rt;
5510 in->sample_rate = in->config.rate;
5511 in->af_period_multiplier = af_period_multiplier;
5512 } else {
5513 in->config = pcm_config_audio_capture;
5514 in->config.rate = config->sample_rate;
5515 in->sample_rate = config->sample_rate;
5516 in->af_period_multiplier = 1;
5517 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305518 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005519
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305520 /* restrict 24 bit capture for unprocessed source only
5521 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
5522 */
5523 if (config->format == AUDIO_FORMAT_DEFAULT) {
5524 config->format = AUDIO_FORMAT_PCM_16_BIT;
5525 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
5526 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
5527 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
5528 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5529 bool ret_error = false;
5530 in->bit_width = 24;
5531 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5532 from HAL is 24_packed and 8_24
5533 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5534 24_packed return error indicating supported format is 24_packed
5535 *> In case of any other source requesting 24 bit or float return error
5536 indicating format supported is 16 bit only.
5537
5538 on error flinger will retry with supported format passed
5539 */
5540 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
5541 (source != AUDIO_SOURCE_CAMCORDER)) {
5542 config->format = AUDIO_FORMAT_PCM_16_BIT;
5543 if (config->sample_rate > 48000)
5544 config->sample_rate = 48000;
5545 ret_error = true;
5546 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
5547 in->config.format = PCM_FORMAT_S24_3LE;
5548 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5549 in->config.format = PCM_FORMAT_S24_LE;
5550 } else {
5551 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
5552 ret_error = true;
5553 }
5554
5555 if (ret_error) {
5556 ret = -EINVAL;
5557 goto err_open;
5558 }
5559 }
5560
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305561 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305562 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
5563 (adev->mode != AUDIO_MODE_IN_CALL)) {
5564 ret = -EINVAL;
5565 goto err_open;
5566 }
5567
5568 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
5569 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005570 if (config->sample_rate == 0)
5571 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5572 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5573 config->sample_rate != 8000) {
5574 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5575 ret = -EINVAL;
5576 goto err_open;
5577 }
5578 if (config->format == AUDIO_FORMAT_DEFAULT)
5579 config->format = AUDIO_FORMAT_PCM_16_BIT;
5580 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5581 config->format = AUDIO_FORMAT_PCM_16_BIT;
5582 ret = -EINVAL;
5583 goto err_open;
5584 }
5585
5586 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5587 in->config = pcm_config_afe_proxy_record;
5588 in->config.channels = channel_count;
5589 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305590 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305591 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
5592 in, config, &channel_mask_updated)) {
5593 if (channel_mask_updated == true) {
5594 ALOGD("%s: return error to retry with updated channel mask (%#x)",
5595 __func__, config->channel_mask);
5596 ret = -EINVAL;
5597 goto err_open;
5598 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05305599 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07005600 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005601 audio_extn_compr_cap_format_supported(config->format) &&
5602 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005603 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305604 } else if (audio_extn_cin_applicable_stream(in)) {
5605 ret = audio_extn_cin_configure_input_stream(in);
5606 if (ret)
5607 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005608 } else {
5609 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005610 if (!in->realtime) {
5611 in->format = config->format;
5612 frame_size = audio_stream_in_frame_size(&in->stream);
5613 buffer_size = get_input_buffer_size(config->sample_rate,
5614 config->format,
5615 channel_count,
5616 is_low_latency);
5617 in->config.period_size = buffer_size / frame_size;
5618 }
5619
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005620#ifndef COMPRESS_VOIP_ENABLED
5621 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5622 (in->config.rate == 8000 || in->config.rate == 16000 ||
5623 in->config.rate == 32000 || in->config.rate == 48000) &&
5624 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5625
5626 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5627 in->config = default_pcm_config_voip_copp;
5628 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5629 in->config.rate = in->sample_rate;
5630#else
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005631 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08005632 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005633 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005634 (in->config.rate == 8000 || in->config.rate == 16000 ||
5635 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005636 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5637 voice_extn_compress_voip_open_input_stream(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005638#endif
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005639 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005640 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005641
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305642 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5643 &adev->streams_input_cfg_list,
5644 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305645 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305646
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005647 /* This stream could be for sound trigger lab,
5648 get sound trigger pcm if present */
5649 audio_extn_sound_trigger_check_and_get_session(in);
5650
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305651 lock_input_stream(in);
5652 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5653 pthread_mutex_lock(&adev->lock);
5654 in->card_status = adev->card_status;
5655 pthread_mutex_unlock(&adev->lock);
5656 pthread_mutex_unlock(&in->lock);
5657
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005658 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005659 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005660 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005661
5662err_open:
5663 free(in);
5664 *stream_in = NULL;
5665 return ret;
5666}
5667
5668static void adev_close_input_stream(struct audio_hw_device *dev,
5669 struct audio_stream_in *stream)
5670{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005671 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005672 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005673 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305674
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305675 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005676
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305677 // must deregister from sndmonitor first to prevent races
5678 // between the callback and close_stream
5679 audio_extn_snd_mon_unregister_listener(stream);
5680
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305681 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005682 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305683
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005684 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305685 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005686 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305687 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005688 if (ret != 0)
5689 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5690 __func__, ret);
5691 } else
5692 in_standby(&stream->common);
5693
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005694 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005695 audio_extn_ssr_deinit();
5696 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005697
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305698 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005699 audio_extn_compr_cap_format_supported(in->config.format))
5700 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305701
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305702 if (audio_extn_cin_attached_usecase(in->usecase))
5703 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005704
Mingming Yinfd7607b2016-01-22 12:48:44 -08005705 if (in->is_st_session) {
5706 ALOGV("%s: sound trigger pcm stop lab", __func__);
5707 audio_extn_sound_trigger_stop_lab(in);
5708 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005709 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005710 return;
5711}
5712
Siddartha Shaik31b530e2017-05-19 15:26:33 +05305713int adev_create_audio_patch(struct audio_hw_device *dev,
5714 unsigned int num_sources,
5715 const struct audio_port_config *sources,
5716 unsigned int num_sinks,
5717 const struct audio_port_config *sinks,
5718 audio_patch_handle_t *handle)
5719{
5720
5721
5722 return audio_extn_hw_loopback_create_audio_patch(dev,
5723 num_sources,
5724 sources,
5725 num_sinks,
5726 sinks,
5727 handle);
5728
5729}
5730
5731int adev_release_audio_patch(struct audio_hw_device *dev,
5732 audio_patch_handle_t handle)
5733{
5734 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
5735}
5736
5737int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
5738{
5739 return audio_extn_hw_loopback_get_audio_port(dev, config);
5740}
5741
5742int adev_set_audio_port_config(struct audio_hw_device *dev,
5743 const struct audio_port_config *config)
5744{
5745 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
5746}
5747
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005748static int adev_dump(const audio_hw_device_t *device __unused,
5749 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005750{
5751 return 0;
5752}
5753
5754static int adev_close(hw_device_t *device)
5755{
5756 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005757
5758 if (!adev)
5759 return 0;
5760
5761 pthread_mutex_lock(&adev_init_lock);
5762
5763 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305764 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005765 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005766 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305767 audio_extn_utils_release_streams_cfg_lists(
5768 &adev->streams_output_cfg_list,
5769 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305770 if (audio_extn_qaf_is_enabled())
5771 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005772 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005773 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005774 free(adev->snd_dev_ref_cnt);
5775 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005776 if (adev->adm_deinit)
5777 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305778 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005779 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305780 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05305781 audio_extn_hw_loopback_deinit(adev);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05305782 if (adev->device_cfg_params) {
5783 free(adev->device_cfg_params);
5784 adev->device_cfg_params = NULL;
5785 }
Kiran Kandi910e1862013-10-29 13:29:42 -07005786 free(device);
5787 adev = NULL;
5788 }
5789 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005790
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005791 return 0;
5792}
5793
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005794/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5795 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5796 * just that it _might_ work.
5797 */
5798static int period_size_is_plausible_for_low_latency(int period_size)
5799{
5800 switch (period_size) {
5801 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005802 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005803 case 240:
5804 case 320:
5805 case 480:
5806 return 1;
5807 default:
5808 return 0;
5809 }
5810}
5811
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305812static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
5813{
5814 bool is_snd_card_status = false;
5815 bool is_ext_device_status = false;
5816 char value[32];
5817 int card = -1;
5818 card_status_t status;
5819
5820 if (cookie != adev || !parms)
5821 return;
5822
5823 if (!parse_snd_card_status(parms, &card, &status)) {
5824 is_snd_card_status = true;
5825 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
5826 is_ext_device_status = true;
5827 } else {
5828 // not a valid event
5829 return;
5830 }
5831
5832 pthread_mutex_lock(&adev->lock);
5833 if (card == adev->snd_card || is_ext_device_status) {
5834 if (is_snd_card_status && adev->card_status != status) {
5835 adev->card_status = status;
5836 platform_snd_card_update(adev->platform, status);
5837 audio_extn_fm_set_parameters(adev, parms);
5838 } else if (is_ext_device_status) {
5839 platform_set_parameters(adev->platform, parms);
5840 }
5841 }
5842 pthread_mutex_unlock(&adev->lock);
5843 return;
5844}
5845
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305846/* out and adev lock held */
5847static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5848{
5849 struct audio_usecase *uc_info;
5850 float left_p;
5851 float right_p;
5852 audio_devices_t devices;
5853
5854 uc_info = get_usecase_from_list(adev, out->usecase);
5855 if (uc_info == NULL) {
5856 ALOGE("%s: Could not find the usecase (%d) in the list",
5857 __func__, out->usecase);
5858 return -EINVAL;
5859 }
5860
5861 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5862 out->usecase, use_case_table[out->usecase]);
5863
5864 if (restore) {
5865 // restore A2DP device for active usecases and unmute if required
5866 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5867 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
5868 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
5869 select_devices(adev, uc_info->id);
5870 pthread_mutex_lock(&out->compr_mute_lock);
5871 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5872 (out->a2dp_compress_mute)) {
5873 out->a2dp_compress_mute = false;
5874 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5875 }
5876 pthread_mutex_unlock(&out->compr_mute_lock);
5877 }
5878 } else {
5879 // mute compress stream if suspended
5880 pthread_mutex_lock(&out->compr_mute_lock);
5881 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5882 (!out->a2dp_compress_mute)) {
5883 if (!out->standby) {
5884 ALOGD("%s: selecting speaker and muting stream", __func__);
5885 devices = out->devices;
5886 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5887 left_p = out->volume_l;
5888 right_p = out->volume_r;
5889 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5890 compress_pause(out->compr);
5891 out_set_compr_volume(&out->stream, (float)0, (float)0);
5892 out->a2dp_compress_mute = true;
5893 select_devices(adev, out->usecase);
5894 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5895 compress_resume(out->compr);
5896 out->devices = devices;
5897 out->volume_l = left_p;
5898 out->volume_r = right_p;
5899 }
5900 }
5901 pthread_mutex_unlock(&out->compr_mute_lock);
5902 }
5903 ALOGV("%s: exit", __func__);
5904 return 0;
5905}
5906
5907int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5908{
5909 int ret = 0;
5910
5911 lock_output_stream(out);
5912 pthread_mutex_lock(&adev->lock);
5913
5914 ret = check_a2dp_restore_l(adev, out, restore);
5915
5916 pthread_mutex_unlock(&adev->lock);
5917 pthread_mutex_unlock(&out->lock);
5918 return ret;
5919}
5920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005921static int adev_open(const hw_module_t *module, const char *name,
5922 hw_device_t **device)
5923{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305924 int ret;
5925
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005926 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005927 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5928
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005929 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005930 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005931 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005932 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005933 ALOGD("%s: returning existing instance of adev", __func__);
5934 ALOGD("%s: exit", __func__);
5935 pthread_mutex_unlock(&adev_init_lock);
5936 return 0;
5937 }
5938
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005939 adev = calloc(1, sizeof(struct audio_device));
5940
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005941 if (!adev) {
5942 pthread_mutex_unlock(&adev_init_lock);
5943 return -ENOMEM;
5944 }
5945
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005946 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5947
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05305948#ifdef DYNAMIC_LOG_ENABLED
5949 register_for_dynamic_logging("hal");
5950#endif
5951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005952 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5953 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5954 adev->device.common.module = (struct hw_module_t *)module;
5955 adev->device.common.close = adev_close;
5956
5957 adev->device.init_check = adev_init_check;
5958 adev->device.set_voice_volume = adev_set_voice_volume;
5959 adev->device.set_master_volume = adev_set_master_volume;
5960 adev->device.get_master_volume = adev_get_master_volume;
5961 adev->device.set_master_mute = adev_set_master_mute;
5962 adev->device.get_master_mute = adev_get_master_mute;
5963 adev->device.set_mode = adev_set_mode;
5964 adev->device.set_mic_mute = adev_set_mic_mute;
5965 adev->device.get_mic_mute = adev_get_mic_mute;
5966 adev->device.set_parameters = adev_set_parameters;
5967 adev->device.get_parameters = adev_get_parameters;
5968 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5969 adev->device.open_output_stream = adev_open_output_stream;
5970 adev->device.close_output_stream = adev_close_output_stream;
5971 adev->device.open_input_stream = adev_open_input_stream;
5972 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05305973 adev->device.create_audio_patch = adev_create_audio_patch;
5974 adev->device.release_audio_patch = adev_release_audio_patch;
5975 adev->device.get_audio_port = adev_get_audio_port;
5976 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005977 adev->device.dump = adev_dump;
5978
5979 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005980 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005981 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005982 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005983 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005984 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005985 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005986 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305987 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005988 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005989 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005990 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005991 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005992 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005993 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305994 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305995 adev->perf_lock_opts[0] = 0x101;
5996 adev->perf_lock_opts[1] = 0x20E;
5997 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08005998 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305999
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006000 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006001 adev->platform = platform_init(adev);
6002 if (!adev->platform) {
6003 free(adev->snd_dev_ref_cnt);
6004 free(adev);
6005 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6006 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08006007 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306008 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006009 return -EINVAL;
6010 }
Eric Laurentc4aef752013-09-12 17:45:53 -07006011
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306012 if (audio_extn_qaf_is_enabled()) {
6013 ret = audio_extn_qaf_init(adev);
6014 if (ret < 0) {
6015 free(adev);
6016 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6017 *device = NULL;
6018 pthread_mutex_unlock(&adev_init_lock);
6019 pthread_mutex_destroy(&adev->lock);
6020 return ret;
6021 }
6022
6023 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
6024 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
6025 }
6026
Eric Laurentc4aef752013-09-12 17:45:53 -07006027 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
6028 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6029 if (adev->visualizer_lib == NULL) {
6030 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6031 } else {
6032 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6033 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006034 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006035 "visualizer_hal_start_output");
6036 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006037 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006038 "visualizer_hal_stop_output");
6039 }
6040 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05306041 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08006042 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006043 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306044 audio_extn_hw_loopback_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07006045
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006046 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
6047 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6048 if (adev->offload_effects_lib == NULL) {
6049 ALOGE("%s: DLOPEN failed for %s", __func__,
6050 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6051 } else {
6052 ALOGV("%s: DLOPEN successful for %s", __func__,
6053 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6054 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05306055 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006056 "offload_effects_bundle_hal_start_output");
6057 adev->offload_effects_stop_output =
6058 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6059 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006060 adev->offload_effects_set_hpx_state =
6061 (int (*)(bool))dlsym(adev->offload_effects_lib,
6062 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05306063 adev->offload_effects_get_parameters =
6064 (void (*)(struct str_parms *, struct str_parms *))
6065 dlsym(adev->offload_effects_lib,
6066 "offload_effects_bundle_get_parameters");
6067 adev->offload_effects_set_parameters =
6068 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
6069 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006070 }
6071 }
6072
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006073 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
6074 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6075 if (adev->adm_lib == NULL) {
6076 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6077 } else {
6078 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6079 adev->adm_init = (adm_init_t)
6080 dlsym(adev->adm_lib, "adm_init");
6081 adev->adm_deinit = (adm_deinit_t)
6082 dlsym(adev->adm_lib, "adm_deinit");
6083 adev->adm_register_input_stream = (adm_register_input_stream_t)
6084 dlsym(adev->adm_lib, "adm_register_input_stream");
6085 adev->adm_register_output_stream = (adm_register_output_stream_t)
6086 dlsym(adev->adm_lib, "adm_register_output_stream");
6087 adev->adm_deregister_stream = (adm_deregister_stream_t)
6088 dlsym(adev->adm_lib, "adm_deregister_stream");
6089 adev->adm_request_focus = (adm_request_focus_t)
6090 dlsym(adev->adm_lib, "adm_request_focus");
6091 adev->adm_abandon_focus = (adm_abandon_focus_t)
6092 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006093 adev->adm_set_config = (adm_set_config_t)
6094 dlsym(adev->adm_lib, "adm_set_config");
6095 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6096 dlsym(adev->adm_lib, "adm_request_focus_v2");
6097 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6098 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6099 adev->adm_on_routing_change = (adm_on_routing_change_t)
6100 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006101 }
6102 }
6103
Mingming Yin514a8bc2014-07-29 15:22:21 -07006104 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006105 //initialize this to false for now,
6106 //this will be set to true through set param
6107 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07006108
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07006109 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006110 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08006111 adev->dsp_bit_width_enforce_mode =
6112 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006113
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306114 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
6115 &adev->streams_output_cfg_list,
6116 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006117
Kiran Kandi910e1862013-10-29 13:29:42 -07006118 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006119
6120 char value[PROPERTY_VALUE_MAX];
6121 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006122 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006123 trial = atoi(value);
6124 if (period_size_is_plausible_for_low_latency(trial)) {
6125 pcm_config_low_latency.period_size = trial;
6126 pcm_config_low_latency.start_threshold = trial / 4;
6127 pcm_config_low_latency.avail_min = trial / 4;
6128 configured_low_latency_capture_period_size = trial;
6129 }
6130 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006131 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006132 trial = atoi(value);
6133 if (period_size_is_plausible_for_low_latency(trial)) {
6134 configured_low_latency_capture_period_size = trial;
6135 }
6136 }
6137
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006138 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006139 af_period_multiplier = atoi(value);
6140 if (af_period_multiplier < 0)
6141 af_period_multiplier = 2;
6142 else if (af_period_multiplier > 4)
6143 af_period_multiplier = 4;
6144
6145 ALOGV("new period_multiplier = %d", af_period_multiplier);
6146 }
6147
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006148 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006149 pthread_mutex_unlock(&adev_init_lock);
6150
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006151 if (adev->adm_init)
6152 adev->adm_data = adev->adm_init();
6153
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306154 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306155 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006156 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306157
6158 audio_extn_snd_mon_init();
6159 pthread_mutex_lock(&adev->lock);
6160 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
6161 adev->card_status = CARD_STATUS_ONLINE;
6162 pthread_mutex_unlock(&adev->lock);
6163 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306164 /* Allocate memory for Device config params */
6165 adev->device_cfg_params = (struct audio_device_config_param*)
6166 calloc(platform_get_max_codec_backend(),
6167 sizeof(struct audio_device_config_param));
6168 if (adev->device_cfg_params == NULL)
6169 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306170
Eric Laurent994a6932013-07-17 11:51:42 -07006171 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006172 return 0;
6173}
6174
6175static struct hw_module_methods_t hal_module_methods = {
6176 .open = adev_open,
6177};
6178
6179struct audio_module HAL_MODULE_INFO_SYM = {
6180 .common = {
6181 .tag = HARDWARE_MODULE_TAG,
6182 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6183 .hal_api_version = HARDWARE_HAL_API_VERSION,
6184 .id = AUDIO_HARDWARE_MODULE_ID,
6185 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08006186 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006187 .methods = &hal_module_methods,
6188 },
6189};