blob: af3a6c5e19a53988da7ee2bd11118ac2bde5a24c [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
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700349static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
350 int flags __unused)
351{
352 int dir = 0;
353 switch (uc_id) {
354 case USECASE_AUDIO_RECORD_LOW_LATENCY:
355 dir = 1;
356 case USECASE_AUDIO_PLAYBACK_ULL:
357 break;
358 default:
359 return false;
360 }
361
362 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
363 PCM_PLAYBACK : PCM_CAPTURE);
364 if (adev->adm_is_noirq_avail)
365 return adev->adm_is_noirq_avail(adev->adm_data,
366 adev->snd_card, dev_id, dir);
367 return false;
368}
369
370static void register_out_stream(struct stream_out *out)
371{
372 struct audio_device *adev = out->dev;
373 if (is_offload_usecase(out->usecase) ||
374 !adev->adm_register_output_stream)
375 return;
376
377 // register stream first for backward compatibility
378 adev->adm_register_output_stream(adev->adm_data,
379 out->handle,
380 out->flags);
381
382 if (!adev->adm_set_config)
383 return;
384
385 if (out->realtime)
386 adev->adm_set_config(adev->adm_data,
387 out->handle,
388 out->pcm, &out->config);
389}
390
391static void register_in_stream(struct stream_in *in)
392{
393 struct audio_device *adev = in->dev;
394 if (!adev->adm_register_input_stream)
395 return;
396
397 adev->adm_register_input_stream(adev->adm_data,
398 in->capture_handle,
399 in->flags);
400
401 if (!adev->adm_set_config)
402 return;
403
404 if (in->realtime)
405 adev->adm_set_config(adev->adm_data,
406 in->capture_handle,
407 in->pcm,
408 &in->config);
409}
410
411static void request_out_focus(struct stream_out *out, long ns)
412{
413 struct audio_device *adev = out->dev;
414
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700415 if (adev->adm_request_focus_v2)
416 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
417 else if (adev->adm_request_focus)
418 adev->adm_request_focus(adev->adm_data, out->handle);
419}
420
421static void request_in_focus(struct stream_in *in, long ns)
422{
423 struct audio_device *adev = in->dev;
424
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700425 if (adev->adm_request_focus_v2)
426 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
427 else if (adev->adm_request_focus)
428 adev->adm_request_focus(adev->adm_data, in->capture_handle);
429}
430
431static void release_out_focus(struct stream_out *out)
432{
433 struct audio_device *adev = out->dev;
434
435 if (adev->adm_abandon_focus)
436 adev->adm_abandon_focus(adev->adm_data, out->handle);
437}
438
439static void release_in_focus(struct stream_in *in)
440{
441 struct audio_device *adev = in->dev;
442 if (adev->adm_abandon_focus)
443 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
444}
445
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530446static int parse_snd_card_status(struct str_parms *parms, int *card,
447 card_status_t *status)
448{
449 char value[32]={0};
450 char state[32]={0};
451
452 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
453 if (ret < 0)
454 return -1;
455
456 // sscanf should be okay as value is of max length 32.
457 // same as sizeof state.
458 if (sscanf(value, "%d,%s", card, state) < 2)
459 return -1;
460
461 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
462 CARD_STATUS_OFFLINE;
463 return 0;
464}
465
vivek mehtaa76401a2015-04-24 14:12:15 -0700466__attribute__ ((visibility ("default")))
467bool audio_hw_send_gain_dep_calibration(int level) {
468 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700469 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700470
471 pthread_mutex_lock(&adev_init_lock);
472
473 if (adev != NULL && adev->platform != NULL) {
474 pthread_mutex_lock(&adev->lock);
475 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700476
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530477 // cache level info for any of the use case which
478 // was not started.
479 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700480
vivek mehtaa76401a2015-04-24 14:12:15 -0700481 pthread_mutex_unlock(&adev->lock);
482 } else {
483 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
484 }
485
486 pthread_mutex_unlock(&adev_init_lock);
487
488 return ret_val;
489}
490
Ashish Jain5106d362016-05-11 19:23:33 +0530491static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
492{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800493 bool gapless_enabled = false;
494 const char *mixer_ctl_name = "Compress Gapless Playback";
495 struct mixer_ctl *ctl;
496
497 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700498 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530499
500 /*Disable gapless if its AV playback*/
501 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800502
503 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
504 if (!ctl) {
505 ALOGE("%s: Could not get ctl for mixer cmd - %s",
506 __func__, mixer_ctl_name);
507 return -EINVAL;
508 }
509
510 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
511 ALOGE("%s: Could not set gapless mode %d",
512 __func__, gapless_enabled);
513 return -EINVAL;
514 }
515 return 0;
516}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700517
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700518__attribute__ ((visibility ("default")))
519int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
520 int table_size) {
521 int ret_val = 0;
522 ALOGV("%s: enter ... ", __func__);
523
524 pthread_mutex_lock(&adev_init_lock);
525 if (adev == NULL) {
526 ALOGW("%s: adev is NULL .... ", __func__);
527 goto done;
528 }
529
530 pthread_mutex_lock(&adev->lock);
531 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
532 pthread_mutex_unlock(&adev->lock);
533done:
534 pthread_mutex_unlock(&adev_init_lock);
535 ALOGV("%s: exit ... ", __func__);
536 return ret_val;
537}
538
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700539static bool is_supported_format(audio_format_t format)
540{
Eric Laurent86e17132013-09-12 17:49:30 -0700541 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530542 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530543 format == AUDIO_FORMAT_AAC_LC ||
544 format == AUDIO_FORMAT_AAC_HE_V1 ||
545 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530546 format == AUDIO_FORMAT_AAC_ADTS_LC ||
547 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
548 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530549 format == AUDIO_FORMAT_AAC_LATM_LC ||
550 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
551 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530552 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
553 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530554 format == AUDIO_FORMAT_PCM_FLOAT ||
555 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700556 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530557 format == AUDIO_FORMAT_AC3 ||
558 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700559 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530560 format == AUDIO_FORMAT_DTS ||
561 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800562 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530563 format == AUDIO_FORMAT_ALAC ||
564 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530565 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530566 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800567 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530568 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700569 format == AUDIO_FORMAT_APTX ||
570 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800571 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700572
573 return false;
574}
575
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700576static inline bool is_mmap_usecase(audio_usecase_t uc_id)
577{
578 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
579 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
580}
581
Avinash Vaish71a8b972014-07-24 15:36:33 +0530582static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
583 struct audio_usecase *uc_info)
584{
585 struct listnode *node;
586 struct audio_usecase *usecase;
587
588 if (uc_info == NULL)
589 return -EINVAL;
590
591 /* Re-route all voice usecases on the shared backend other than the
592 specified usecase to new snd devices */
593 list_for_each(node, &adev->usecase_list) {
594 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800595 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530596 enable_audio_route(adev, usecase);
597 }
598 return 0;
599}
600
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530601static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530602{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530603 ALOGV("%s", __func__);
604 audio_route_apply_and_update_path(adev->audio_route,
605 "asrc-mode");
606 adev->asrc_mode_enabled = true;
607}
608
609static void disable_asrc_mode(struct audio_device *adev)
610{
611 ALOGV("%s", __func__);
612 audio_route_reset_and_update_path(adev->audio_route,
613 "asrc-mode");
614 adev->asrc_mode_enabled = false;
615}
616
617/*
618 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
619 * 44.1 or Native DSD backends are enabled for any of current use case.
620 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
621 * - Disable current mix path use case(Headphone backend) and re-enable it with
622 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
623 * e.g. Naitve DSD or Headphone 44.1 -> + 48
624 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530625static void check_and_set_asrc_mode(struct audio_device *adev,
626 struct audio_usecase *uc_info,
627 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530628{
629 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530630 int i, num_new_devices = 0;
631 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
632 /*
633 *Split snd device for new combo use case
634 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
635 */
636 if (platform_split_snd_device(adev->platform,
637 snd_device,
638 &num_new_devices,
639 split_new_snd_devices) == 0) {
640 for (i = 0; i < num_new_devices; i++)
641 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
642 } else {
643 int new_backend_idx = platform_get_backend_index(snd_device);
644 if (((new_backend_idx == HEADPHONE_BACKEND) ||
645 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
646 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
647 !adev->asrc_mode_enabled) {
648 struct listnode *node = NULL;
649 struct audio_usecase *uc = NULL;
650 struct stream_out *curr_out = NULL;
651 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
652 int i, num_devices, ret = 0;
653 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530654
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530655 list_for_each(node, &adev->usecase_list) {
656 uc = node_to_item(node, struct audio_usecase, list);
657 curr_out = (struct stream_out*) uc->stream.out;
658 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
659 /*
660 *Split snd device for existing combo use case
661 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
662 */
663 ret = platform_split_snd_device(adev->platform,
664 uc->out_snd_device,
665 &num_devices,
666 split_snd_devices);
667 if (ret < 0 || num_devices == 0) {
668 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
669 split_snd_devices[0] = uc->out_snd_device;
670 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800671 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530672 for (i = 0; i < num_devices; i++) {
673 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
674 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
675 if((new_backend_idx == HEADPHONE_BACKEND) &&
676 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
677 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
678 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
679 __func__);
680 enable_asrc_mode(adev);
681 break;
682 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
683 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
684 (usecase_backend_idx == HEADPHONE_BACKEND)) {
685 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
686 __func__);
687 disable_audio_route(adev, uc);
688 disable_snd_device(adev, uc->out_snd_device);
689 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
690 if (new_backend_idx == DSD_NATIVE_BACKEND)
691 audio_route_apply_and_update_path(adev->audio_route,
692 "hph-true-highquality-mode");
693 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
694 (curr_out->bit_width >= 24))
695 audio_route_apply_and_update_path(adev->audio_route,
696 "hph-highquality-mode");
697 enable_asrc_mode(adev);
698 enable_snd_device(adev, uc->out_snd_device);
699 enable_audio_route(adev, uc);
700 break;
701 }
702 }
703 // reset split devices count
704 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800705 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530706 if (adev->asrc_mode_enabled)
707 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530708 }
709 }
710 }
711}
712
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700713int pcm_ioctl(struct pcm *pcm, int request, ...)
714{
715 va_list ap;
716 void * arg;
717 int pcm_fd = *(int*)pcm;
718
719 va_start(ap, request);
720 arg = va_arg(ap, void *);
721 va_end(ap);
722
723 return ioctl(pcm_fd, request, arg);
724}
725
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700726int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700727 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800728{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700729 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700730 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530731 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800732
733 if (usecase == NULL)
734 return -EINVAL;
735
736 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
737
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800738 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700739 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800740 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700741 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800742
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800743#ifdef DS1_DOLBY_DAP_ENABLED
744 audio_extn_dolby_set_dmid(adev);
745 audio_extn_dolby_set_endpoint(adev);
746#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700747 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700748 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530749 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700750 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530751 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530752 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
753 out = usecase->stream.out;
754 if (out && out->compr)
755 audio_extn_utils_compress_set_clk_rec_mode(usecase);
756 }
757
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800758 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700759 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700760 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700761 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800762 ALOGV("%s: exit", __func__);
763 return 0;
764}
765
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700766int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700767 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800768{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700769 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700770 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800771
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530772 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800773 return -EINVAL;
774
775 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700776 if (usecase->type == PCM_CAPTURE)
777 snd_device = usecase->in_snd_device;
778 else
779 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800780 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700781 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700782 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700783 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700784 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530785 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800786 ALOGV("%s: exit", __func__);
787 return 0;
788}
789
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700790int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700791 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800792{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530793 int i, num_devices = 0;
794 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700795 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
796
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800797 if (snd_device < SND_DEVICE_MIN ||
798 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800799 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800800 return -EINVAL;
801 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700802
803 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700804
805 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
806 ALOGE("%s: Invalid sound device returned", __func__);
807 return -EINVAL;
808 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700809 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700810 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700811 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700812 return 0;
813 }
814
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530815
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700816 if (audio_extn_spkr_prot_is_enabled())
817 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700818
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800819 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
820 audio_extn_spkr_prot_is_enabled()) {
821 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700822 adev->snd_dev_ref_cnt[snd_device]--;
823 return -EINVAL;
824 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200825 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800826 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800827 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200828 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800829 return -EINVAL;
830 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700831 } else if (platform_split_snd_device(adev->platform,
832 snd_device,
833 &num_devices,
834 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530835 for (i = 0; i < num_devices; i++) {
836 enable_snd_device(adev, new_snd_devices[i]);
837 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800838 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700839 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530840
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530841
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530842 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
843 (audio_extn_a2dp_start_playback() < 0)) {
844 ALOGE(" fail to configure A2dp control path ");
845 return -EINVAL;
846 }
847
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700848 /* due to the possibility of calibration overwrite between listen
849 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700850 audio_extn_sound_trigger_update_device_status(snd_device,
851 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530852 audio_extn_listen_update_device_status(snd_device,
853 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700854 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700855 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700856 audio_extn_sound_trigger_update_device_status(snd_device,
857 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530858 audio_extn_listen_update_device_status(snd_device,
859 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700860 return -EINVAL;
861 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300862 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700863 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530864
865 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
866 !adev->native_playback_enabled &&
867 audio_is_true_native_stream_active(adev)) {
868 ALOGD("%s: %d: napb: enabling native mode in hardware",
869 __func__, __LINE__);
870 audio_route_apply_and_update_path(adev->audio_route,
871 "true-native-mode");
872 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530873 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800874 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800875 return 0;
876}
877
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700878int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700879 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800880{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530881 int i, num_devices = 0;
882 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700883 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
884
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800885 if (snd_device < SND_DEVICE_MIN ||
886 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800887 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800888 return -EINVAL;
889 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700890 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
891 ALOGE("%s: device ref cnt is already 0", __func__);
892 return -EINVAL;
893 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700894
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700895 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700896
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700897 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
898 ALOGE("%s: Invalid sound device returned", __func__);
899 return -EINVAL;
900 }
901
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700902 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700903 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530904
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800905 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
906 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700907 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700908 } else if (platform_split_snd_device(adev->platform,
909 snd_device,
910 &num_devices,
911 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530912 for (i = 0; i < num_devices; i++) {
913 disable_snd_device(adev, new_snd_devices[i]);
914 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300915 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700916 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300917 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700918
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530919 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
920 audio_extn_a2dp_stop_playback();
921
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700922 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530923 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530924 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
925 adev->native_playback_enabled) {
926 ALOGD("%s: %d: napb: disabling native mode in hardware",
927 __func__, __LINE__);
928 audio_route_reset_and_update_path(adev->audio_route,
929 "true-native-mode");
930 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530931 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
932 adev->asrc_mode_enabled) {
933 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530934 disable_asrc_mode(adev);
935 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530936 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530937
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200938 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700939 audio_extn_sound_trigger_update_device_status(snd_device,
940 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530941 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800942 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700943 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700944
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800945 return 0;
946}
947
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700948/*
949 legend:
950 uc - existing usecase
951 new_uc - new usecase
952 d1, d11, d2 - SND_DEVICE enums
953 a1, a2 - corresponding ANDROID device enums
954 B1, B2 - backend strings
955
956case 1
957 uc->dev d1 (a1) B1
958 new_uc->dev d1 (a1), d2 (a2) B1, B2
959
960 resolution: disable and enable uc->dev on d1
961
962case 2
963 uc->dev d1 (a1) B1
964 new_uc->dev d11 (a1) B1
965
966 resolution: need to switch uc since d1 and d11 are related
967 (e.g. speaker and voice-speaker)
968 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
969
970case 3
971 uc->dev d1 (a1) B1
972 new_uc->dev d2 (a2) B2
973
974 resolution: no need to switch uc
975
976case 4
977 uc->dev d1 (a1) B1
978 new_uc->dev d2 (a2) B1
979
980 resolution: disable enable uc-dev on d2 since backends match
981 we cannot enable two streams on two different devices if they
982 share the same backend. e.g. if offload is on speaker device using
983 QUAD_MI2S backend and a low-latency stream is started on voice-handset
984 using the same backend, offload must also be switched to voice-handset.
985
986case 5
987 uc->dev d1 (a1) B1
988 new_uc->dev d1 (a1), d2 (a2) B1
989
990 resolution: disable enable uc-dev on d2 since backends match
991 we cannot enable two streams on two different devices if they
992 share the same backend.
993
994case 6
995 uc->dev d1 (a1) B1
996 new_uc->dev d2 (a1) B2
997
998 resolution: no need to switch
999
1000case 7
1001 uc->dev d1 (a1), d2 (a2) B1, B2
1002 new_uc->dev d1 (a1) B1
1003
1004 resolution: no need to switch
1005
1006*/
1007static snd_device_t derive_playback_snd_device(void * platform,
1008 struct audio_usecase *uc,
1009 struct audio_usecase *new_uc,
1010 snd_device_t new_snd_device)
1011{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301012 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001013
1014 snd_device_t d1 = uc->out_snd_device;
1015 snd_device_t d2 = new_snd_device;
1016
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301017 switch (uc->type) {
1018 case TRANSCODE_LOOPBACK :
1019 a1 = uc->stream.inout->out_config.devices;
1020 a2 = new_uc->stream.inout->out_config.devices;
1021 break;
1022 default :
1023 a1 = uc->stream.out->devices;
1024 a2 = new_uc->stream.out->devices;
1025 break;
1026 }
1027
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001028 // Treat as a special case when a1 and a2 are not disjoint
1029 if ((a1 != a2) && (a1 & a2)) {
1030 snd_device_t d3[2];
1031 int num_devices = 0;
1032 int ret = platform_split_snd_device(platform,
1033 popcount(a1) > 1 ? d1 : d2,
1034 &num_devices,
1035 d3);
1036 if (ret < 0) {
1037 if (ret != -ENOSYS) {
1038 ALOGW("%s failed to split snd_device %d",
1039 __func__,
1040 popcount(a1) > 1 ? d1 : d2);
1041 }
1042 goto end;
1043 }
1044
1045 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1046 // But if it does happen, we need to give priority to d2 if
1047 // the combo devices active on the existing usecase share a backend.
1048 // This is because we cannot have a usecase active on a combo device
1049 // and a new usecase requests one device in this combo pair.
1050 if (platform_check_backends_match(d3[0], d3[1])) {
1051 return d2; // case 5
1052 } else {
1053 return d1; // case 1
1054 }
1055 } else {
1056 if (platform_check_backends_match(d1, d2)) {
1057 return d2; // case 2, 4
1058 } else {
1059 return d1; // case 6, 3
1060 }
1061 }
1062
1063end:
1064 return d2; // return whatever was calculated before.
1065}
1066
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001067static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301068 struct audio_usecase *uc_info,
1069 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001070{
1071 struct listnode *node;
1072 struct audio_usecase *usecase;
1073 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301074 snd_device_t uc_derive_snd_device;
1075 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001076 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001077 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301078 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001079 /*
1080 * This function is to make sure that all the usecases that are active on
1081 * the hardware codec backend are always routed to any one device that is
1082 * handled by the hardware codec.
1083 * For example, if low-latency and deep-buffer usecases are currently active
1084 * on speaker and out_set_parameters(headset) is received on low-latency
1085 * output, then we have to make sure deep-buffer is also switched to headset,
1086 * because of the limitation that both the devices cannot be enabled
1087 * at the same time as they share the same backend.
1088 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001089 /*
1090 * This call is to check if we need to force routing for a particular stream
1091 * If there is a backend configuration change for the device when a
1092 * new stream starts, then ADM needs to be closed and re-opened with the new
1093 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001094 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001095 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001096 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1097 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301098 /* For a2dp device reconfigure all active sessions
1099 * with new AFE encoder format based on a2dp state
1100 */
1101 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1102 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1103 audio_extn_a2dp_is_force_device_switch()) {
1104 force_routing = true;
1105 force_restart_session = true;
1106 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301107 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1108
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001109 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001110 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001111 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001112 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1113 switch_device[i] = false;
1114
1115 list_for_each(node, &adev->usecase_list) {
1116 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001117
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301118 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1119 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301120 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301121 platform_get_snd_device_name(usecase->out_snd_device),
1122 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301123 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1124 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1125 usecase, uc_info, snd_device);
1126 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1127 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1128 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1129 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1130 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1131 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1132 ((force_restart_session) ||
1133 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301134 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1135 __func__, use_case_table[usecase->id],
1136 platform_get_snd_device_name(usecase->out_snd_device));
1137 disable_audio_route(adev, usecase);
1138 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301139 /* Enable existing usecase on derived playback device */
1140 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301141 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301142 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001143 }
1144 }
1145
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301146 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1147 num_uc_to_switch);
1148
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001149 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001150 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001151
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301152 /* Make sure the previous devices to be disabled first and then enable the
1153 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001154 list_for_each(node, &adev->usecase_list) {
1155 usecase = node_to_item(node, struct audio_usecase, list);
1156 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001157 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001158 }
1159 }
1160
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001161 list_for_each(node, &adev->usecase_list) {
1162 usecase = node_to_item(node, struct audio_usecase, list);
1163 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301164 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001165 }
1166 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001167
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001168 /* Re-route all the usecases on the shared backend other than the
1169 specified usecase to new snd devices */
1170 list_for_each(node, &adev->usecase_list) {
1171 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301172 /* Update the out_snd_device only before enabling the audio route */
1173 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301174 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301175 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301176 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301177 use_case_table[usecase->id],
1178 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001179 /* Update voc calibration before enabling VoIP route */
1180 if (usecase->type == VOIP_CALL)
1181 status = platform_switch_voice_call_device_post(adev->platform,
1182 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001183 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301184 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301185 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001186 }
1187 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001188 }
1189}
1190
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301191static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001192 struct audio_usecase *uc_info,
1193 snd_device_t snd_device)
1194{
1195 struct listnode *node;
1196 struct audio_usecase *usecase;
1197 bool switch_device[AUDIO_USECASE_MAX];
1198 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301199 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001200 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001201
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301202 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1203 snd_device);
1204 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301205
1206 /*
1207 * Make sure out devices is checked against out codec backend device and
1208 * also in devices against in codec backend. Checking out device against in
1209 * codec backend or vice versa causes issues.
1210 */
1211 if (uc_info->type == PCM_CAPTURE)
1212 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001213 /*
1214 * This function is to make sure that all the active capture usecases
1215 * are always routed to the same input sound device.
1216 * For example, if audio-record and voice-call usecases are currently
1217 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1218 * is received for voice call then we have to make sure that audio-record
1219 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1220 * because of the limitation that two devices cannot be enabled
1221 * at the same time if they share the same backend.
1222 */
1223 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1224 switch_device[i] = false;
1225
1226 list_for_each(node, &adev->usecase_list) {
1227 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301228 /*
1229 * TODO: Enhance below condition to handle BT sco/USB multi recording
1230 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001231 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001232 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301233 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301234 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301235 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301236 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001237 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001238 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1239 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001240 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001241 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001242 switch_device[usecase->id] = true;
1243 num_uc_to_switch++;
1244 }
1245 }
1246
1247 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001248 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001249
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301250 /* Make sure the previous devices to be disabled first and then enable the
1251 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001252 list_for_each(node, &adev->usecase_list) {
1253 usecase = node_to_item(node, struct audio_usecase, list);
1254 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001255 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001256 }
1257 }
1258
1259 list_for_each(node, &adev->usecase_list) {
1260 usecase = node_to_item(node, struct audio_usecase, list);
1261 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001262 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001263 }
1264 }
1265
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001266 /* Re-route all the usecases on the shared backend other than the
1267 specified usecase to new snd devices */
1268 list_for_each(node, &adev->usecase_list) {
1269 usecase = node_to_item(node, struct audio_usecase, list);
1270 /* Update the in_snd_device only before enabling the audio route */
1271 if (switch_device[usecase->id] ) {
1272 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001273 if (usecase->type != VOICE_CALL) {
1274 /* Update voc calibration before enabling VoIP route */
1275 if (usecase->type == VOIP_CALL)
1276 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001277 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001278 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301279 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001280 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001281 }
1282 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001283 }
1284}
1285
Mingming Yin3a941d42016-02-17 18:08:05 -08001286static void reset_hdmi_sink_caps(struct stream_out *out) {
1287 int i = 0;
1288
1289 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1290 out->supported_channel_masks[i] = 0;
1291 }
1292 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1293 out->supported_formats[i] = 0;
1294 }
1295 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1296 out->supported_sample_rates[i] = 0;
1297 }
1298}
1299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001300/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001301static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001302{
Mingming Yin3a941d42016-02-17 18:08:05 -08001303 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001304 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001305
Mingming Yin3a941d42016-02-17 18:08:05 -08001306 reset_hdmi_sink_caps(out);
1307
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001308 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001309 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001310 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001311 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001312 }
1313
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001314 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001315 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001316 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001317 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001318 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1319 case 6:
1320 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1321 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1322 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1323 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1324 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1325 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001326 break;
1327 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001328 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001329 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001330 break;
1331 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001332
1333 // check channel format caps
1334 i = 0;
1335 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1336 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1337 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1338 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1339 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1340 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1341 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1342 }
1343
Ben Romberger1aaaf862017-04-06 17:49:46 -07001344 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1345 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1346 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1347 }
1348
Mingming Yin3a941d42016-02-17 18:08:05 -08001349 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1350 ALOGV(":%s HDMI supports DTS format", __func__);
1351 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1352 }
1353
1354 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1355 ALOGV(":%s HDMI supports DTS HD format", __func__);
1356 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1357 }
1358
Naresh Tanniru928f0862017-04-07 16:44:23 -07001359 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1360 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1361 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1362 }
1363
Mingming Yin3a941d42016-02-17 18:08:05 -08001364
1365 // check sample rate caps
1366 i = 0;
1367 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1368 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1369 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1370 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1371 }
1372 }
1373
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001374 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001375}
1376
Alexy Josephb1379942016-01-29 15:49:38 -08001377audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001378 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001379{
1380 struct audio_usecase *usecase;
1381 struct listnode *node;
1382
1383 list_for_each(node, &adev->usecase_list) {
1384 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001385 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001386 ALOGV("%s: usecase id %d", __func__, usecase->id);
1387 return usecase->id;
1388 }
1389 }
1390 return USECASE_INVALID;
1391}
1392
Alexy Josephb1379942016-01-29 15:49:38 -08001393struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001394 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001395{
1396 struct audio_usecase *usecase;
1397 struct listnode *node;
1398
1399 list_for_each(node, &adev->usecase_list) {
1400 usecase = node_to_item(node, struct audio_usecase, list);
1401 if (usecase->id == uc_id)
1402 return usecase;
1403 }
1404 return NULL;
1405}
1406
Dhananjay Kumard4833242016-10-06 22:09:12 +05301407struct stream_in *get_next_active_input(const struct audio_device *adev)
1408{
1409 struct audio_usecase *usecase;
1410 struct listnode *node;
1411
1412 list_for_each_reverse(node, &adev->usecase_list) {
1413 usecase = node_to_item(node, struct audio_usecase, list);
1414 if (usecase->type == PCM_CAPTURE)
1415 return usecase->stream.in;
1416 }
1417 return NULL;
1418}
1419
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301420/*
1421 * is a true native playback active
1422 */
1423bool audio_is_true_native_stream_active(struct audio_device *adev)
1424{
1425 bool active = false;
1426 int i = 0;
1427 struct listnode *node;
1428
1429 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1430 ALOGV("%s:napb: not in true mode or non hdphones device",
1431 __func__);
1432 active = false;
1433 goto exit;
1434 }
1435
1436 list_for_each(node, &adev->usecase_list) {
1437 struct audio_usecase *uc;
1438 uc = node_to_item(node, struct audio_usecase, list);
1439 struct stream_out *curr_out =
1440 (struct stream_out*) uc->stream.out;
1441
1442 if (curr_out && PCM_PLAYBACK == uc->type) {
1443 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1444 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1445 uc->id, curr_out->sample_rate,
1446 curr_out->bit_width,
1447 platform_get_snd_device_name(uc->out_snd_device));
1448
1449 if (is_offload_usecase(uc->id) &&
1450 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1451 active = true;
1452 ALOGD("%s:napb:native stream detected", __func__);
1453 }
1454 }
1455 }
1456exit:
1457 return active;
1458}
1459
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301460/*
1461 * if native DSD playback active
1462 */
1463bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1464{
1465 bool active = false;
1466 struct listnode *node = NULL;
1467 struct audio_usecase *uc = NULL;
1468 struct stream_out *curr_out = NULL;
1469
1470 list_for_each(node, &adev->usecase_list) {
1471 uc = node_to_item(node, struct audio_usecase, list);
1472 curr_out = (struct stream_out*) uc->stream.out;
1473
1474 if (curr_out && PCM_PLAYBACK == uc->type &&
1475 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1476 active = true;
1477 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301478 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301479 }
1480 }
1481 return active;
1482}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301483
1484static bool force_device_switch(struct audio_usecase *usecase)
1485{
1486 bool ret = false;
1487 bool is_it_true_mode = false;
1488
1489 if (is_offload_usecase(usecase->id) &&
1490 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001491 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1492 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1493 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301494 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1495 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1496 (!is_it_true_mode && adev->native_playback_enabled)){
1497 ret = true;
1498 ALOGD("napb: time to toggle native mode");
1499 }
1500 }
1501
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301502 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301503 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1504 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301505 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001506 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301507 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301508 ALOGD("Force a2dp device switch to update new encoder config");
1509 ret = true;
1510 }
1511
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301512 return ret;
1513}
1514
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301515bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1516{
1517 bool ret=false;
1518 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1519 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1520 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1521 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1522 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1523 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1524 ret = true;
1525
1526 return ret;
1527}
1528
1529bool is_a2dp_device(snd_device_t out_snd_device)
1530{
1531 bool ret=false;
1532 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1533 ret = true;
1534
1535 return ret;
1536}
1537
1538bool is_bt_soc_on(struct audio_device *adev)
1539{
1540 struct mixer_ctl *ctl;
1541 char *mixer_ctl_name = "BT SOC status";
1542 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1543 bool bt_soc_status = true;
1544 if (!ctl) {
1545 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1546 __func__, mixer_ctl_name);
1547 /*This is to ensure we dont break targets which dont have the kernel change*/
1548 return true;
1549 }
1550 bt_soc_status = mixer_ctl_get_value(ctl, 0);
1551 ALOGD("BT SOC status: %d",bt_soc_status);
1552 return bt_soc_status;
1553}
1554
1555int out_standby_l(struct audio_stream *stream);
1556
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001557int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001558{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001559 snd_device_t out_snd_device = SND_DEVICE_NONE;
1560 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001561 struct audio_usecase *usecase = NULL;
1562 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001563 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001564 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001565 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001566 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301568 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1569
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001570 usecase = get_usecase_from_list(adev, uc_id);
1571 if (usecase == NULL) {
1572 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1573 return -EINVAL;
1574 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001575
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001576 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001577 (usecase->type == VOIP_CALL) ||
1578 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301579 if(usecase->stream.out == NULL) {
1580 ALOGE("%s: stream.out is NULL", __func__);
1581 return -EINVAL;
1582 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001583 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001584 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001585 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001586 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301587 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
1588 if (usecase->stream.inout == NULL) {
1589 ALOGE("%s: stream.inout is NULL", __func__);
1590 return -EINVAL;
1591 }
1592 out_snd_device = usecase->stream.inout->out_config.devices;
1593 in_snd_device = usecase->stream.inout->in_config.devices;
1594 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001595 } else {
1596 /*
1597 * If the voice call is active, use the sound devices of voice call usecase
1598 * so that it would not result any device switch. All the usecases will
1599 * be switched to new device when select_devices() is called for voice call
1600 * usecase. This is to avoid switching devices for voice call when
1601 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001602 * choose voice call device only if the use case device is
1603 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001604 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001605 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001606 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001607 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001608 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1609 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301610 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1611 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001612 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001613 in_snd_device = vc_usecase->in_snd_device;
1614 out_snd_device = vc_usecase->out_snd_device;
1615 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001616 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001617 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001618 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001619 if ((voip_usecase != NULL) &&
1620 (usecase->type == PCM_PLAYBACK) &&
1621 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001622 out_snd_device_backend_match = platform_check_backends_match(
1623 voip_usecase->out_snd_device,
1624 platform_get_output_snd_device(
1625 adev->platform,
1626 usecase->stream.out));
1627 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001628 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001629 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1630 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001631 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001632 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001633 in_snd_device = voip_usecase->in_snd_device;
1634 out_snd_device = voip_usecase->out_snd_device;
1635 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001636 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001637 hfp_ucid = audio_extn_hfp_get_usecase();
1638 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001639 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001640 in_snd_device = hfp_usecase->in_snd_device;
1641 out_snd_device = hfp_usecase->out_snd_device;
1642 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001643 }
1644 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301645 if (usecase->stream.out == NULL) {
1646 ALOGE("%s: stream.out is NULL", __func__);
1647 return -EINVAL;
1648 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001649 usecase->devices = usecase->stream.out->devices;
1650 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001651 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001652 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001653 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001654 if (usecase->stream.out == adev->primary_output &&
1655 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001656 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001657 select_devices(adev, adev->active_input->usecase);
1658 }
1659 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001660 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301661 if (usecase->stream.in == NULL) {
1662 ALOGE("%s: stream.in is NULL", __func__);
1663 return -EINVAL;
1664 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001665 usecase->devices = usecase->stream.in->device;
1666 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001667 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001668 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001669 if (adev->active_input &&
1670 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301671 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1672 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1673 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001674 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001675 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001676 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1677 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001678 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001679 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001680 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001681 }
1682 }
1683
1684 if (out_snd_device == usecase->out_snd_device &&
1685 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301686
1687 if (!force_device_switch(usecase))
1688 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689 }
1690
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301691 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
1692 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
1693 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1694 return 0;
1695 }
1696
sangwoobc677242013-08-08 16:53:43 +09001697 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001698 out_snd_device, platform_get_snd_device_name(out_snd_device),
1699 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701 /*
1702 * Limitation: While in call, to do a device switch we need to disable
1703 * and enable both RX and TX devices though one of them is same as current
1704 * device.
1705 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001706 if ((usecase->type == VOICE_CALL) &&
1707 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1708 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001709 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001710 }
1711
1712 if (((usecase->type == VOICE_CALL) ||
1713 (usecase->type == VOIP_CALL)) &&
1714 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1715 /* Disable sidetone only if voice/voip call already exists */
1716 if (voice_is_call_state_active(adev) ||
1717 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001718 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001719
1720 /* Disable aanc only if voice call exists */
1721 if (voice_is_call_state_active(adev))
1722 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001723 }
1724
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001725 /* Disable current sound devices */
1726 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001727 disable_audio_route(adev, usecase);
1728 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729 }
1730
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001731 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001732 disable_audio_route(adev, usecase);
1733 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001734 }
1735
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001736 /* Applicable only on the targets that has external modem.
1737 * New device information should be sent to modem before enabling
1738 * the devices to reduce in-call device switch time.
1739 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001740 if ((usecase->type == VOICE_CALL) &&
1741 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1742 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001743 status = platform_switch_voice_call_enable_device_config(adev->platform,
1744 out_snd_device,
1745 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001746 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001747
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001748 /* Enable new sound devices */
1749 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001750 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301751 if (platform_check_codec_asrc_support(adev->platform))
1752 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001753 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754 }
1755
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001756 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301757 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001758 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001759 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001760
Avinash Vaish71a8b972014-07-24 15:36:33 +05301761 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001762 status = platform_switch_voice_call_device_post(adev->platform,
1763 out_snd_device,
1764 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301765 enable_audio_route_for_voice_usecases(adev, usecase);
1766 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001767
sangwoo170731f2013-06-08 15:36:36 +09001768 usecase->in_snd_device = in_snd_device;
1769 usecase->out_snd_device = out_snd_device;
1770
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301771 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1772 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301773 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001774 if ((24 == usecase->stream.out->bit_width) &&
1775 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1776 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1777 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1778 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1779 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1780 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1781 /*
1782 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1783 * configured device sample rate, if not update the COPP rate to be equal to the
1784 * device sample rate, else open COPP at stream sample rate
1785 */
1786 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1787 usecase->stream.out->sample_rate,
1788 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301789 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1790 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001791 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1792 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1793 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1794 }
1795
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001796 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001797 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001798 audio_extn_gef_notify_device_config(
1799 usecase->stream.out->devices,
1800 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001801 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001802 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001803 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301804 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001805 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001806
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001807 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001808 /* Enable aanc only if voice call exists */
1809 if (voice_is_call_state_active(adev))
1810 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1811
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001812 /* Enable sidetone only if other voice/voip call already exists */
1813 if (voice_is_call_state_active(adev) ||
1814 voice_extn_compress_voip_is_started(adev))
1815 voice_set_sidetone(adev, out_snd_device, true);
1816 }
1817
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001818 /* Applicable only on the targets that has external modem.
1819 * Enable device command should be sent to modem only after
1820 * enabling voice call mixer controls
1821 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001822 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001823 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1824 out_snd_device,
1825 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301826
1827 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
1828
1829 if (usecase->type == VOIP_CALL) {
1830 if (adev->active_input != NULL &&
1831 !adev->active_input->standby) {
1832 if (is_bt_soc_on(adev) == false){
1833 ALOGD("BT SCO MIC disconnected while in connection");
1834 if (adev->active_input->pcm != NULL)
1835 pcm_stop(adev->active_input->pcm);
1836 }
1837 }
1838 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
1839 && usecase->stream.out->started) {
1840 if (is_bt_soc_on(adev) == false) {
1841 ALOGD("BT SCO/A2DP disconnected while in connection");
1842 out_standby_l(&usecase->stream.out->stream.common);
1843 }
1844 }
1845 } else if ((usecase->stream.out != NULL) &&
1846 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
1847 usecase->stream.out->started) {
1848 if (is_bt_soc_on(adev) == false) {
1849 ALOGD("BT SCO/A2dp disconnected while in connection");
1850 out_standby_l(&usecase->stream.out->stream.common);
1851 }
1852 }
1853 }
1854
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301855 ALOGD("%s: done",__func__);
1856
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001857 return status;
1858}
1859
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001860static int stop_input_stream(struct stream_in *in)
1861{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301862 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863 struct audio_usecase *uc_info;
1864 struct audio_device *adev = in->dev;
1865
Eric Laurent994a6932013-07-17 11:51:42 -07001866 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001867 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001868 uc_info = get_usecase_from_list(adev, in->usecase);
1869 if (uc_info == NULL) {
1870 ALOGE("%s: Could not find the usecase (%d) in the list",
1871 __func__, in->usecase);
1872 return -EINVAL;
1873 }
1874
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001875 /* Close in-call recording streams */
1876 voice_check_and_stop_incall_rec_usecase(adev, in);
1877
Eric Laurent150dbfe2013-02-27 14:31:02 -08001878 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001879 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001880
1881 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001882 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001884 list_remove(&uc_info->list);
1885 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001887 adev->active_input = get_next_active_input(adev);
1888
Eric Laurent994a6932013-07-17 11:51:42 -07001889 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001890 return ret;
1891}
1892
1893int start_input_stream(struct stream_in *in)
1894{
1895 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001896 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897 struct audio_usecase *uc_info;
1898 struct audio_device *adev = in->dev;
1899
Mingming Yin2664a5b2015-09-03 10:53:11 -07001900 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1901 if (get_usecase_from_list(adev, usecase) == NULL)
1902 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301903 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1904 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001905
Naresh Tanniru80659832014-06-04 18:17:56 +05301906
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05301907 if (CARD_STATUS_OFFLINE == in->card_status||
1908 CARD_STATUS_OFFLINE == adev->card_status) {
1909 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301910 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301911 goto error_config;
1912 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301913
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301914 if (audio_is_bluetooth_sco_device(in->device)) {
1915 if (!adev->bt_sco_on) {
1916 ALOGE("%s: SCO profile is not ready, return error", __func__);
1917 ret = -EIO;
1918 goto error_config;
1919 }
1920 }
1921
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001922 /* Check if source matches incall recording usecase criteria */
1923 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1924 if (ret)
1925 goto error_config;
1926 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001927 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1928
1929 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1930 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1931 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001932 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001933 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001934
Eric Laurentb23d5282013-05-14 15:27:20 -07001935 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001936 if (in->pcm_device_id < 0) {
1937 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1938 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001939 ret = -EINVAL;
1940 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001941 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001942
1943 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001944 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001945
1946 if (!uc_info) {
1947 ret = -ENOMEM;
1948 goto error_config;
1949 }
1950
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001951 uc_info->id = in->usecase;
1952 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001953 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001954 uc_info->devices = in->device;
1955 uc_info->in_snd_device = SND_DEVICE_NONE;
1956 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001957
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001958 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301959 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1960 adev->perf_lock_opts,
1961 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001962 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001963
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301964 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1965 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001966
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301967 if (audio_extn_cin_attached_usecase(in->usecase)) {
1968 ret = audio_extn_cin_start_input_stream(in);
1969 if (ret)
1970 goto error_open;
1971 else
1972 goto done_open;
1973 }
1974
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001975 unsigned int flags = PCM_IN;
1976 unsigned int pcm_open_retry_count = 0;
1977
1978 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1979 flags |= PCM_MMAP | PCM_NOIRQ;
1980 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001981 } else if (in->realtime) {
1982 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001983 }
1984
1985 while (1) {
1986 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1987 flags, &in->config);
1988 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1989 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1990 if (in->pcm != NULL) {
1991 pcm_close(in->pcm);
1992 in->pcm = NULL;
1993 }
1994 if (pcm_open_retry_count-- == 0) {
1995 ret = -EIO;
1996 goto error_open;
1997 }
1998 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1999 continue;
2000 }
2001 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002003
2004 ALOGV("%s: pcm_prepare", __func__);
2005 ret = pcm_prepare(in->pcm);
2006 if (ret < 0) {
2007 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2008 pcm_close(in->pcm);
2009 in->pcm = NULL;
2010 goto error_open;
2011 }
2012
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002013 register_in_stream(in);
2014 if (in->realtime) {
2015 ret = pcm_start(in->pcm);
2016 if (ret < 0)
2017 goto error_open;
2018 }
2019
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302020done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302021 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002022 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002023
Eric Laurentc8400632013-02-14 19:04:54 -08002024 return ret;
2025
2026error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302027 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002029error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302030 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302031 /*
2032 * sleep 50ms to allow sufficient time for kernel
2033 * drivers to recover incases like SSR.
2034 */
2035 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002036 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002037
2038 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002039}
2040
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002041void lock_input_stream(struct stream_in *in)
2042{
2043 pthread_mutex_lock(&in->pre_lock);
2044 pthread_mutex_lock(&in->lock);
2045 pthread_mutex_unlock(&in->pre_lock);
2046}
2047
2048void lock_output_stream(struct stream_out *out)
2049{
2050 pthread_mutex_lock(&out->pre_lock);
2051 pthread_mutex_lock(&out->lock);
2052 pthread_mutex_unlock(&out->pre_lock);
2053}
2054
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002055/* must be called with out->lock locked */
2056static int send_offload_cmd_l(struct stream_out* out, int command)
2057{
2058 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2059
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002060 if (!cmd) {
2061 ALOGE("failed to allocate mem for command 0x%x", command);
2062 return -ENOMEM;
2063 }
2064
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002065 ALOGVV("%s %d", __func__, command);
2066
2067 cmd->cmd = command;
2068 list_add_tail(&out->offload_cmd_list, &cmd->node);
2069 pthread_cond_signal(&out->offload_cond);
2070 return 0;
2071}
2072
2073/* must be called iwth out->lock locked */
2074static void stop_compressed_output_l(struct stream_out *out)
2075{
2076 out->offload_state = OFFLOAD_STATE_IDLE;
2077 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002078 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002079 if (out->compr != NULL) {
2080 compress_stop(out->compr);
2081 while (out->offload_thread_blocked) {
2082 pthread_cond_wait(&out->cond, &out->lock);
2083 }
2084 }
2085}
2086
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002087bool is_offload_usecase(audio_usecase_t uc_id)
2088{
2089 unsigned int i;
2090 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2091 if (uc_id == offload_usecases[i])
2092 return true;
2093 }
2094 return false;
2095}
2096
Dhananjay Kumarac341582017-02-23 23:42:25 +05302097static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002098{
vivek mehta446c3962015-09-14 10:57:35 -07002099 audio_usecase_t ret_uc = USECASE_INVALID;
2100 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002101 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002102 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302103 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002104 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2105 else
2106 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002107
vivek mehta446c3962015-09-14 10:57:35 -07002108 pthread_mutex_lock(&adev->lock);
2109 if (get_usecase_from_list(adev, ret_uc) != NULL)
2110 ret_uc = USECASE_INVALID;
2111 pthread_mutex_unlock(&adev->lock);
2112
2113 return ret_uc;
2114 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002115
2116 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002117 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2118 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2119 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2120 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002121 break;
2122 }
2123 }
vivek mehta446c3962015-09-14 10:57:35 -07002124
2125 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2126 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002127}
2128
2129static void free_offload_usecase(struct audio_device *adev,
2130 audio_usecase_t uc_id)
2131{
vivek mehta446c3962015-09-14 10:57:35 -07002132 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002133 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002134
2135 if (!adev->multi_offload_enable)
2136 return;
2137
2138 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2139 if (offload_usecases[offload_uc_index] == uc_id) {
2140 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002141 break;
2142 }
2143 }
2144 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2145}
2146
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002147static void *offload_thread_loop(void *context)
2148{
2149 struct stream_out *out = (struct stream_out *) context;
2150 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002151 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002152
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002153 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2154 set_sched_policy(0, SP_FOREGROUND);
2155 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2156
2157 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002158 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002159 for (;;) {
2160 struct offload_cmd *cmd = NULL;
2161 stream_callback_event_t event;
2162 bool send_callback = false;
2163
2164 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2165 __func__, list_empty(&out->offload_cmd_list),
2166 out->offload_state);
2167 if (list_empty(&out->offload_cmd_list)) {
2168 ALOGV("%s SLEEPING", __func__);
2169 pthread_cond_wait(&out->offload_cond, &out->lock);
2170 ALOGV("%s RUNNING", __func__);
2171 continue;
2172 }
2173
2174 item = list_head(&out->offload_cmd_list);
2175 cmd = node_to_item(item, struct offload_cmd, node);
2176 list_remove(item);
2177
2178 ALOGVV("%s STATE %d CMD %d out->compr %p",
2179 __func__, out->offload_state, cmd->cmd, out->compr);
2180
2181 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2182 free(cmd);
2183 break;
2184 }
2185
2186 if (out->compr == NULL) {
2187 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002188 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002189 pthread_cond_signal(&out->cond);
2190 continue;
2191 }
2192 out->offload_thread_blocked = true;
2193 pthread_mutex_unlock(&out->lock);
2194 send_callback = false;
2195 switch(cmd->cmd) {
2196 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002197 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002198 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002199 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002200 send_callback = true;
2201 event = STREAM_CBK_EVENT_WRITE_READY;
2202 break;
2203 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002204 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302205 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002206 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302207 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002208 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302209 if (ret < 0)
2210 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302211 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302212 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002213 compress_drain(out->compr);
2214 else
2215 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302216 if (ret != -ENETRESET) {
2217 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302218 pthread_mutex_lock(&out->lock);
2219 out->send_new_metadata = 1;
2220 out->send_next_track_params = true;
2221 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302222 event = STREAM_CBK_EVENT_DRAIN_READY;
2223 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2224 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302225 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002226 break;
2227 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002228 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002229 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002230 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002231 send_callback = true;
2232 event = STREAM_CBK_EVENT_DRAIN_READY;
2233 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302234 case OFFLOAD_CMD_ERROR:
2235 ALOGD("copl(%p): sending error callback to AF", out);
2236 send_callback = true;
2237 event = STREAM_CBK_EVENT_ERROR;
2238 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002239 default:
2240 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2241 break;
2242 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002243 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002244 out->offload_thread_blocked = false;
2245 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002246 if (send_callback && out->client_callback) {
2247 ALOGVV("%s: sending client_callback event %d", __func__, event);
2248 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002249 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002250 free(cmd);
2251 }
2252
2253 pthread_cond_signal(&out->cond);
2254 while (!list_empty(&out->offload_cmd_list)) {
2255 item = list_head(&out->offload_cmd_list);
2256 list_remove(item);
2257 free(node_to_item(item, struct offload_cmd, node));
2258 }
2259 pthread_mutex_unlock(&out->lock);
2260
2261 return NULL;
2262}
2263
2264static int create_offload_callback_thread(struct stream_out *out)
2265{
2266 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2267 list_init(&out->offload_cmd_list);
2268 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2269 offload_thread_loop, out);
2270 return 0;
2271}
2272
2273static int destroy_offload_callback_thread(struct stream_out *out)
2274{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002275 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002276 stop_compressed_output_l(out);
2277 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2278
2279 pthread_mutex_unlock(&out->lock);
2280 pthread_join(out->offload_thread, (void **) NULL);
2281 pthread_cond_destroy(&out->offload_cond);
2282
2283 return 0;
2284}
2285
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286static int stop_output_stream(struct stream_out *out)
2287{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302288 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002289 struct audio_usecase *uc_info;
2290 struct audio_device *adev = out->dev;
2291
Eric Laurent994a6932013-07-17 11:51:42 -07002292 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002293 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294 uc_info = get_usecase_from_list(adev, out->usecase);
2295 if (uc_info == NULL) {
2296 ALOGE("%s: Could not find the usecase (%d) in the list",
2297 __func__, out->usecase);
2298 return -EINVAL;
2299 }
2300
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002301 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302302 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002303 if (adev->visualizer_stop_output != NULL)
2304 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002305
2306 audio_extn_dts_remove_state_notifier_node(out->usecase);
2307
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002308 if (adev->offload_effects_stop_output != NULL)
2309 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2310 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002311
Eric Laurent150dbfe2013-02-27 14:31:02 -08002312 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002313 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002314
2315 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002316 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002317
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002318 list_remove(&uc_info->list);
2319 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302320 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002321 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302322 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002323 ALOGV("Disable passthrough , reset mixer to pcm");
2324 /* NO_PASSTHROUGH */
2325 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002326 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002327 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2328 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002329
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302330 /* Must be called after removing the usecase from list */
2331 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302332 audio_extn_keep_alive_start();
2333
Naresh Tanniru85819452017-05-04 18:55:45 -07002334 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
2335 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2336 if (ret < 0)
2337 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2338 }
2339
Eric Laurent994a6932013-07-17 11:51:42 -07002340 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341 return ret;
2342}
2343
2344int start_output_stream(struct stream_out *out)
2345{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347 struct audio_usecase *uc_info;
2348 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002349 char mixer_ctl_name[128];
2350 struct mixer_ctl *ctl = NULL;
2351 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002353 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2354 ret = -EINVAL;
2355 goto error_config;
2356 }
2357
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302358 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2359 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2360 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302361
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302362 if (CARD_STATUS_OFFLINE == out->card_status ||
2363 CARD_STATUS_OFFLINE == adev->card_status) {
2364 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302365 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302366 goto error_config;
2367 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302368
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302369 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2370 if (!audio_extn_a2dp_is_ready()) {
2371 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2372 //combo usecase just by pass a2dp
2373 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2374 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2375 } else {
2376 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2377 ret = -EAGAIN;
2378 goto error_config;
2379 }
2380 }
2381 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302382 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2383 if (!adev->bt_sco_on) {
2384 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2385 //combo usecase just by pass a2dp
2386 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
2387 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2388 } else {
2389 ALOGE("%s: SCO profile is not ready, return error", __func__);
2390 ret = -EAGAIN;
2391 goto error_config;
2392 }
2393 }
2394 }
2395
Eric Laurentb23d5282013-05-14 15:27:20 -07002396 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002397 if (out->pcm_device_id < 0) {
2398 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2399 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002400 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002401 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002402 }
2403
2404 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002405
2406 if (!uc_info) {
2407 ret = -ENOMEM;
2408 goto error_config;
2409 }
2410
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002411 uc_info->id = out->usecase;
2412 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002413 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002414 uc_info->devices = out->devices;
2415 uc_info->in_snd_device = SND_DEVICE_NONE;
2416 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002417 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002418
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302419 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2420 adev->perf_lock_opts,
2421 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302422
2423 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2424 audio_extn_keep_alive_stop();
2425 if (audio_extn_passthru_is_enabled() &&
2426 audio_extn_passthru_is_passthrough_stream(out)) {
2427 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302428 }
2429 }
2430
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002431 select_devices(adev, out->usecase);
2432
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002433 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2434 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002435 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002436 unsigned int flags = PCM_OUT;
2437 unsigned int pcm_open_retry_count = 0;
2438 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2439 flags |= PCM_MMAP | PCM_NOIRQ;
2440 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002441 } else if (out->realtime) {
2442 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002443 } else
2444 flags |= PCM_MONOTONIC;
2445
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002446 if ((adev->vr_audio_mode_enabled) &&
2447 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2448 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2449 "PCM_Dev %d Topology", out->pcm_device_id);
2450 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2451 if (!ctl) {
2452 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2453 __func__, mixer_ctl_name);
2454 } else {
2455 //if success use ULLPP
2456 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2457 __func__, mixer_ctl_name, out->pcm_device_id);
2458 //There is a still a possibility that some sessions
2459 // that request for FAST|RAW when 3D audio is active
2460 //can go through ULLPP. Ideally we expects apps to
2461 //listen to audio focus and stop concurrent playback
2462 //Also, we will look for mode flag (voice_in_communication)
2463 //before enabling the realtime flag.
2464 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2465 }
2466 }
2467
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002468 while (1) {
2469 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2470 flags, &out->config);
2471 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2472 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2473 if (out->pcm != NULL) {
2474 pcm_close(out->pcm);
2475 out->pcm = NULL;
2476 }
2477 if (pcm_open_retry_count-- == 0) {
2478 ret = -EIO;
2479 goto error_open;
2480 }
2481 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2482 continue;
2483 }
2484 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002485 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002486
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002487 ALOGV("%s: pcm_prepare", __func__);
2488 if (pcm_is_ready(out->pcm)) {
2489 ret = pcm_prepare(out->pcm);
2490 if (ret < 0) {
2491 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2492 pcm_close(out->pcm);
2493 out->pcm = NULL;
2494 goto error_open;
2495 }
2496 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302497 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302498 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
2499
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002500 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002501 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302502 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002504 out->compr = compress_open(adev->snd_card,
2505 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002506 COMPRESS_IN, &out->compr_config);
2507 if (out->compr && !is_compress_ready(out->compr)) {
2508 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2509 compress_close(out->compr);
2510 out->compr = NULL;
2511 ret = -EIO;
2512 goto error_open;
2513 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302514 /* compress_open sends params of the track, so reset the flag here */
2515 out->is_compr_metadata_avail = false;
2516
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002517 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002518 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002519
Fred Oh3f43e742015-03-04 18:42:34 -08002520 /* Since small bufs uses blocking writes, a write will be blocked
2521 for the default max poll time (20s) in the event of an SSR.
2522 Reduce the poll time to observe and deal with SSR faster.
2523 */
Ashish Jain5106d362016-05-11 19:23:33 +05302524 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002525 compress_set_max_poll_wait(out->compr, 1000);
2526 }
2527
Manish Dewangan69426c82017-01-30 17:35:36 +05302528 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302529 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05302530
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002531 audio_extn_dts_create_state_notifier_node(out->usecase);
2532 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2533 popcount(out->channel_mask),
2534 out->playback_started);
2535
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002536#ifdef DS1_DOLBY_DDP_ENABLED
2537 if (audio_extn_is_dolby_format(out->format))
2538 audio_extn_dolby_send_ddp_endp_params(adev);
2539#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302540 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2541 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002542 if (adev->visualizer_start_output != NULL)
2543 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2544 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302545 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002546 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002547 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002549
2550 if (ret == 0) {
2551 register_out_stream(out);
2552 if (out->realtime) {
2553 ret = pcm_start(out->pcm);
2554 if (ret < 0)
2555 goto error_open;
2556 }
2557 }
2558
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302559 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002560 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002561
Naresh Tanniru85819452017-05-04 18:55:45 -07002562 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07002563 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07002564 if (ret < 0)
2565 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
2566 }
2567
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002568 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002569error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302570 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002572error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302573 /*
2574 * sleep 50ms to allow sufficient time for kernel
2575 * drivers to recover incases like SSR.
2576 */
2577 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002578 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579}
2580
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581static int check_input_parameters(uint32_t sample_rate,
2582 audio_format_t format,
2583 int channel_count)
2584{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002585 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302587 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2588 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2589 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002590 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302591 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002592
2593 switch (channel_count) {
2594 case 1:
2595 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302596 case 3:
2597 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002598 case 6:
2599 break;
2600 default:
2601 ret = -EINVAL;
2602 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603
2604 switch (sample_rate) {
2605 case 8000:
2606 case 11025:
2607 case 12000:
2608 case 16000:
2609 case 22050:
2610 case 24000:
2611 case 32000:
2612 case 44100:
2613 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302614 case 96000:
2615 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616 break;
2617 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002618 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619 }
2620
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002621 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622}
2623
2624static size_t get_input_buffer_size(uint32_t sample_rate,
2625 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002626 int channel_count,
2627 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628{
2629 size_t size = 0;
2630
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002631 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2632 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002634 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002635 if (is_low_latency)
2636 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302637
2638 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002640 /* make sure the size is multiple of 32 bytes
2641 * At 48 kHz mono 16-bit PCM:
2642 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2643 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2644 */
2645 size += 0x1f;
2646 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002647
2648 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649}
2650
Ashish Jain058165c2016-09-28 23:18:48 +05302651static size_t get_output_period_size(uint32_t sample_rate,
2652 audio_format_t format,
2653 int channel_count,
2654 int duration /*in millisecs*/)
2655{
2656 size_t size = 0;
2657 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2658
2659 if ((duration == 0) || (sample_rate == 0) ||
2660 (bytes_per_sample == 0) || (channel_count == 0)) {
2661 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2662 bytes_per_sample, channel_count);
2663 return -EINVAL;
2664 }
2665
2666 size = (sample_rate *
2667 duration *
2668 bytes_per_sample *
2669 channel_count) / 1000;
2670 /*
2671 * To have same PCM samples for all channels, the buffer size requires to
2672 * be multiple of (number of channels * bytes per sample)
2673 * For writes to succeed, the buffer must be written at address which is multiple of 32
2674 */
2675 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2676
2677 return (size/(channel_count * bytes_per_sample));
2678}
2679
Ashish Jain5106d362016-05-11 19:23:33 +05302680static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2681{
2682 uint64_t actual_frames_rendered = 0;
2683 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2684
2685 /* This adjustment accounts for buffering after app processor.
2686 * It is based on estimated DSP latency per use case, rather than exact.
2687 */
2688 int64_t platform_latency = platform_render_latency(out->usecase) *
2689 out->sample_rate / 1000000LL;
2690
2691 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2692 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2693 * hence only estimate.
2694 */
2695 int64_t signed_frames = out->written - kernel_buffer_size;
2696
2697 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2698
2699 if (signed_frames > 0)
2700 actual_frames_rendered = signed_frames;
2701
2702 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2703 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2704 (long long int)out->written, (int)kernel_buffer_size,
2705 audio_bytes_per_sample(out->compr_config.codec->format),
2706 popcount(out->channel_mask));
2707
2708 return actual_frames_rendered;
2709}
2710
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2712{
2713 struct stream_out *out = (struct stream_out *)stream;
2714
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002715 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716}
2717
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002718static int out_set_sample_rate(struct audio_stream *stream __unused,
2719 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720{
2721 return -ENOSYS;
2722}
2723
2724static size_t out_get_buffer_size(const struct audio_stream *stream)
2725{
2726 struct stream_out *out = (struct stream_out *)stream;
2727
Naresh Tanniruee3499a2017-01-05 14:05:35 +05302728 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2729 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
2730 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
2731 else
2732 return out->compr_config.fragment_size;
2733 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002734 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07002735 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
2736 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 +05302737 else if (is_offload_usecase(out->usecase) &&
2738 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302739 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002740
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002741 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002742 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743}
2744
2745static uint32_t out_get_channels(const struct audio_stream *stream)
2746{
2747 struct stream_out *out = (struct stream_out *)stream;
2748
2749 return out->channel_mask;
2750}
2751
2752static audio_format_t out_get_format(const struct audio_stream *stream)
2753{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002754 struct stream_out *out = (struct stream_out *)stream;
2755
2756 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757}
2758
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002759static int out_set_format(struct audio_stream *stream __unused,
2760 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761{
2762 return -ENOSYS;
2763}
2764
2765static int out_standby(struct audio_stream *stream)
2766{
2767 struct stream_out *out = (struct stream_out *)stream;
2768 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002769
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302770 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2771 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002773 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002775 if (adev->adm_deregister_stream)
2776 adev->adm_deregister_stream(adev->adm_data, out->handle);
2777
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002778 if (is_offload_usecase(out->usecase))
2779 stop_compressed_output_l(out);
2780
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002781 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002783 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2784 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302785 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08002786 pthread_mutex_unlock(&adev->lock);
2787 pthread_mutex_unlock(&out->lock);
2788 ALOGD("VOIP output entered standby");
2789 return 0;
2790 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002791 if (out->pcm) {
2792 pcm_close(out->pcm);
2793 out->pcm = NULL;
2794 }
2795 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002796 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302797 out->send_next_track_params = false;
2798 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002799 out->gapless_mdata.encoder_delay = 0;
2800 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002801 if (out->compr != NULL) {
2802 compress_close(out->compr);
2803 out->compr = NULL;
2804 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002805 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002807 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808 }
2809 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302810 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811 return 0;
2812}
2813
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302814static int out_on_error(struct audio_stream *stream)
2815{
2816 struct stream_out *out = (struct stream_out *)stream;
2817 bool do_standby = false;
2818
2819 lock_output_stream(out);
2820 if (!out->standby) {
2821 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2822 stop_compressed_output_l(out);
2823 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2824 } else
2825 do_standby = true;
2826 }
2827 pthread_mutex_unlock(&out->lock);
2828
2829 if (do_standby)
2830 return out_standby(&out->stream.common);
2831
2832 return 0;
2833}
2834
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302835/*
2836 *standby implementation without locks, assumes that the callee already
2837 *has taken adev and out lock.
2838 */
2839int out_standby_l(struct audio_stream *stream)
2840{
2841 struct stream_out *out = (struct stream_out *)stream;
2842 struct audio_device *adev = out->dev;
2843
2844 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2845 stream, out->usecase, use_case_table[out->usecase]);
2846
2847 if (!out->standby) {
2848 if (adev->adm_deregister_stream)
2849 adev->adm_deregister_stream(adev->adm_data, out->handle);
2850
2851 if (is_offload_usecase(out->usecase))
2852 stop_compressed_output_l(out);
2853
2854 out->standby = true;
2855 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2856 voice_extn_compress_voip_close_output_stream(stream);
2857 out->started = 0;
2858 ALOGD("VOIP output entered standby");
2859 return 0;
2860 } else if (!is_offload_usecase(out->usecase)) {
2861 if (out->pcm) {
2862 pcm_close(out->pcm);
2863 out->pcm = NULL;
2864 }
2865 } else {
2866 ALOGD("copl(%p):standby", out);
2867 out->send_next_track_params = false;
2868 out->is_compr_metadata_avail = false;
2869 out->gapless_mdata.encoder_delay = 0;
2870 out->gapless_mdata.encoder_padding = 0;
2871 if (out->compr != NULL) {
2872 compress_close(out->compr);
2873 out->compr = NULL;
2874 }
2875 }
2876 stop_output_stream(out);
2877 }
2878 ALOGD("%s: exit", __func__);
2879 return 0;
2880}
2881
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002882static int out_dump(const struct audio_stream *stream __unused,
2883 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002884{
2885 return 0;
2886}
2887
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002888static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2889{
2890 int ret = 0;
2891 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002892
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002893 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002894 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002895 return -EINVAL;
2896 }
2897
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302898 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002899
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002900 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2901 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302902 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002903 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002904 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2905 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302906 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002907 }
2908
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002909 ALOGV("%s new encoder delay %u and padding %u", __func__,
2910 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2911
2912 return 0;
2913}
2914
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002915static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2916{
2917 return out == adev->primary_output || out == adev->voice_tx_output;
2918}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002919
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302920// note: this call is safe only if the stream_cb is
2921// removed first in close_output_stream (as is done now).
2922static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2923{
2924 if (!stream || !parms)
2925 return;
2926
2927 struct stream_out *out = (struct stream_out *)stream;
2928 struct audio_device *adev = out->dev;
2929
2930 card_status_t status;
2931 int card;
2932 if (parse_snd_card_status(parms, &card, &status) < 0)
2933 return;
2934
2935 pthread_mutex_lock(&adev->lock);
2936 bool valid_cb = (card == adev->snd_card);
2937 pthread_mutex_unlock(&adev->lock);
2938
2939 if (!valid_cb)
2940 return;
2941
2942 lock_output_stream(out);
2943 if (out->card_status != status)
2944 out->card_status = status;
2945 pthread_mutex_unlock(&out->lock);
2946
2947 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
2948 use_case_table[out->usecase],
2949 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2950
2951 if (status == CARD_STATUS_OFFLINE)
2952 out_on_error(stream);
2953
2954 return;
2955}
2956
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002957static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2958{
2959 struct stream_out *out = (struct stream_out *)stream;
2960 struct audio_device *adev = out->dev;
2961 struct str_parms *parms;
2962 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002963 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964
sangwoobc677242013-08-08 16:53:43 +09002965 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002966 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002967 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302968 if (!parms)
2969 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002970 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2971 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002973 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002974 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002975
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002976 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002977 * When HDMI cable is unplugged the music playback is paused and
2978 * the policy manager sends routing=0. But the audioflinger continues
2979 * to write data until standby time (3sec). As the HDMI core is
2980 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002981 * Avoid this by routing audio to speaker until standby.
2982 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002983 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2984 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302985 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002986 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2987 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002988 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302989 /*
2990 * When A2DP is disconnected the
2991 * music playback is paused and the policy manager sends routing=0
2992 * But the audioflingercontinues to write data until standby time
2993 * (3sec). As BT is turned off, the write gets blocked.
2994 * Avoid this by routing audio to speaker until standby.
2995 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002996 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302997 (val == AUDIO_DEVICE_NONE)) {
2998 val = AUDIO_DEVICE_OUT_SPEAKER;
2999 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303000 /* To avoid a2dp to sco overlapping / BT device improper state
3001 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303002 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303003 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3004 if (!audio_extn_a2dp_is_ready()) {
3005 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3006 //combo usecase just by pass a2dp
3007 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
3008 val = AUDIO_DEVICE_OUT_SPEAKER;
3009 } else {
3010 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3011 /* update device to a2dp and don't route as BT returned error
3012 * However it is still possible a2dp routing called because
3013 * of current active device disconnection (like wired headset)
3014 */
3015 out->devices = val;
3016 pthread_mutex_unlock(&out->lock);
3017 pthread_mutex_unlock(&adev->lock);
3018 goto error;
3019 }
3020 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303021 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003022 /*
3023 * select_devices() call below switches all the usecases on the same
3024 * backend to the new device. Refer to check_usecases_codec_backend() in
3025 * the select_devices(). But how do we undo this?
3026 *
3027 * For example, music playback is active on headset (deep-buffer usecase)
3028 * and if we go to ringtones and select a ringtone, low-latency usecase
3029 * will be started on headset+speaker. As we can't enable headset+speaker
3030 * and headset devices at the same time, select_devices() switches the music
3031 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3032 * So when the ringtone playback is completed, how do we undo the same?
3033 *
3034 * We are relying on the out_set_parameters() call on deep-buffer output,
3035 * once the ringtone playback is ended.
3036 * NOTE: We should not check if the current devices are same as new devices.
3037 * Because select_devices() must be called to switch back the music
3038 * playback to headset.
3039 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003040 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003041 audio_devices_t new_dev = val;
3042 bool same_dev = out->devices == new_dev;
3043 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003044
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003045 if (output_drives_call(adev, out)) {
3046 if(!voice_is_in_call(adev)) {
3047 if (adev->mode == AUDIO_MODE_IN_CALL) {
3048 adev->current_call_output = out;
3049 ret = voice_start_call(adev);
3050 }
3051 } else {
3052 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003053 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003054 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003055 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003056
3057 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003058 if (!same_dev) {
3059 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303060 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3061 adev->perf_lock_opts,
3062 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003063 if (adev->adm_on_routing_change)
3064 adev->adm_on_routing_change(adev->adm_data,
3065 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003066 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003067 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05303068 if (!same_dev)
3069 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003070 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003071 }
3072
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003074 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003076
3077 if (out == adev->primary_output) {
3078 pthread_mutex_lock(&adev->lock);
3079 audio_extn_set_parameters(adev, parms);
3080 pthread_mutex_unlock(&adev->lock);
3081 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003082 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003083 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003084 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003085
3086 audio_extn_dts_create_state_notifier_node(out->usecase);
3087 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3088 popcount(out->channel_mask),
3089 out->playback_started);
3090
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003091 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003092 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003093
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303094 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3095 if (err >= 0) {
3096 strlcpy(out->profile, value, sizeof(out->profile));
3097 ALOGV("updating stream profile with value '%s'", out->profile);
3098 lock_output_stream(out);
3099 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3100 &adev->streams_output_cfg_list,
3101 out->devices, out->flags, out->format,
3102 out->sample_rate, out->bit_width,
3103 out->channel_mask, out->profile,
3104 &out->app_type_cfg);
3105 pthread_mutex_unlock(&out->lock);
3106 }
3107
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003108 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303109error:
Eric Laurent994a6932013-07-17 11:51:42 -07003110 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111 return ret;
3112}
3113
3114static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3115{
3116 struct stream_out *out = (struct stream_out *)stream;
3117 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003118 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119 char value[256];
3120 struct str_parms *reply = str_parms_create();
3121 size_t i, j;
3122 int ret;
3123 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003124
3125 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003126 if (reply) {
3127 str_parms_destroy(reply);
3128 }
3129 if (query) {
3130 str_parms_destroy(query);
3131 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003132 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
3133 return NULL;
3134 }
3135
Eric Laurent994a6932013-07-17 11:51:42 -07003136 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
3138 if (ret >= 0) {
3139 value[0] = '\0';
3140 i = 0;
3141 while (out->supported_channel_masks[i] != 0) {
3142 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
3143 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
3144 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003145 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003147 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148 first = false;
3149 break;
3150 }
3151 }
3152 i++;
3153 }
3154 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3155 str = str_parms_to_str(reply);
3156 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003157 voice_extn_out_get_parameters(out, query, reply);
3158 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003160
Alexy Joseph62142aa2015-11-16 15:10:34 -08003161
3162 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
3163 if (ret >= 0) {
3164 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05303165 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
3166 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08003167 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303168 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003169 } else {
3170 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05303171 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003172 }
3173 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003174 if (str)
3175 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08003176 str = str_parms_to_str(reply);
3177 }
3178
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003179 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
3180 if (ret >= 0) {
3181 value[0] = '\0';
3182 i = 0;
3183 first = true;
3184 while (out->supported_formats[i] != 0) {
3185 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
3186 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
3187 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003188 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003189 }
3190 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
3191 first = false;
3192 break;
3193 }
3194 }
3195 i++;
3196 }
3197 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003198 if (str)
3199 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003200 str = str_parms_to_str(reply);
3201 }
Mingming Yin3a941d42016-02-17 18:08:05 -08003202
3203 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
3204 if (ret >= 0) {
3205 value[0] = '\0';
3206 i = 0;
3207 first = true;
3208 while (out->supported_sample_rates[i] != 0) {
3209 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
3210 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
3211 if (!first) {
3212 strlcat(value, "|", sizeof(value));
3213 }
3214 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
3215 first = false;
3216 break;
3217 }
3218 }
3219 i++;
3220 }
3221 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
3222 if (str)
3223 free(str);
3224 str = str_parms_to_str(reply);
3225 }
3226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003227 str_parms_destroy(query);
3228 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003229 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230 return str;
3231}
3232
3233static uint32_t out_get_latency(const struct audio_stream_out *stream)
3234{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003235 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08003237 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238
Alexy Josephaa54c872014-12-03 02:46:47 -08003239 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05303240 lock_output_stream(out);
3241 latency = audio_extn_utils_compress_get_dsp_latency(out);
3242 pthread_mutex_unlock(&out->lock);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003243 } else if (out->realtime) {
3244 // since the buffer won't be filled up faster than realtime,
3245 // return a smaller number
3246 if (out->config.rate)
3247 period_ms = (out->af_period_multiplier * out->config.period_size *
3248 1000) / (out->config.rate);
3249 else
3250 period_ms = 0;
3251 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003252 } else {
3253 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003254 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003255 }
3256
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003257 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
3258 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3259 latency += audio_extn_a2dp_get_encoder_latency();
3260
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303261 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003262 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263}
3264
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303265static float AmpToDb(float amplification)
3266{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303267 float db = DSD_VOLUME_MIN_DB;
3268 if (amplification > 0) {
3269 db = 20 * log10(amplification);
3270 if(db < DSD_VOLUME_MIN_DB)
3271 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303272 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303273 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303274}
3275
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276static int out_set_volume(struct audio_stream_out *stream, float left,
3277 float right)
3278{
Eric Laurenta9024de2013-04-04 09:19:12 -07003279 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003280 int volume[2];
3281
Eric Laurenta9024de2013-04-04 09:19:12 -07003282 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3283 /* only take left channel into account: the API is for stereo anyway */
3284 out->muted = (left == 0.0f);
3285 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003286 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303287 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003288 /*
3289 * Set mute or umute on HDMI passthrough stream.
3290 * Only take left channel into account.
3291 * Mute is 0 and unmute 1
3292 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303293 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303294 } else if (out->format == AUDIO_FORMAT_DSD){
3295 char mixer_ctl_name[128] = "DSD Volume";
3296 struct audio_device *adev = out->dev;
3297 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3298
3299 if (!ctl) {
3300 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3301 __func__, mixer_ctl_name);
3302 return -EINVAL;
3303 }
3304 volume[0] = (int)(AmpToDb(left));
3305 volume[1] = (int)(AmpToDb(right));
3306 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3307 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003308 } else {
3309 char mixer_ctl_name[128];
3310 struct audio_device *adev = out->dev;
3311 struct mixer_ctl *ctl;
3312 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003313 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003314
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003315 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3316 "Compress Playback %d Volume", pcm_device_id);
3317 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3318 if (!ctl) {
3319 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3320 __func__, mixer_ctl_name);
3321 return -EINVAL;
3322 }
3323 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3324 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3325 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3326 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003327 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003328 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
3329 char mixer_ctl_name[] = "App Type Gain";
3330 struct audio_device *adev = out->dev;
3331 struct mixer_ctl *ctl;
3332 uint32_t set_values[4];
3333
3334 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3335 if (!ctl) {
3336 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3337 __func__, mixer_ctl_name);
3338 return -EINVAL;
3339 }
3340
3341 set_values[0] = 0; //0: Rx Session 1:Tx Session
3342 set_values[1] = out->app_type_cfg.app_type;
3343 set_values[2] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3344 set_values[3] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3345
3346 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
3347 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003348 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350 return -ENOSYS;
3351}
3352
3353static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3354 size_t bytes)
3355{
3356 struct stream_out *out = (struct stream_out *)stream;
3357 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003358 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003360 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303361
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303362 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003363
Dhananjay Kumarac341582017-02-23 23:42:25 +05303364 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303365 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303366 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3367 pthread_mutex_unlock(&out->lock);
3368 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303369 } else {
3370 /* increase written size during SSR to avoid mismatch
3371 * with the written frames count in AF
3372 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003373 // bytes per frame
3374 size_t bpf = audio_bytes_per_sample(out->format) *
3375 audio_channel_count_from_out_mask(out->channel_mask);
3376 if (bpf != 0)
3377 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303378 ALOGD(" %s: sound card is not active/SSR state", __func__);
3379 ret= -EIO;
3380 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303381 }
3382 }
3383
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303384 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303385 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ben Romberger4863ed72017-06-23 14:25:27 -07003386 if ((audio_bytes_per_sample(out->format) != 0) && (out->config.channels != 0))
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303387 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3388 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303389 goto exit;
3390 }
3391
Manish Dewangan37864bc2017-06-09 12:28:37 +05303392 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3393 /*ADD audio_extn_passthru_is_passthrough_stream(out) check*/
3394 if ((audio_extn_passthru_is_enabled()) &&
3395 (!out->is_iec61937_info_available)) {
3396 audio_extn_passthru_update_stream_configuration(adev, out,
3397 buffer, bytes);
3398 out->is_iec61937_info_available = true;
3399 }
3400 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003402 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003403 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003404 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3405 ret = voice_extn_compress_voip_start_output_stream(out);
3406 else
3407 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003408 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003409 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003410 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003411 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412 goto exit;
3413 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303414 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003415 if (last_known_cal_step != -1) {
3416 ALOGD("%s: retry previous failed cal level set", __func__);
3417 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05303418 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003419 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421
Ashish Jain81eb2a82015-05-13 10:52:34 +05303422 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003423 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303424 adev->is_channel_status_set = true;
3425 }
3426
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003427 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003428 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003429 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003430 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003431 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3432 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303433 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3434 ALOGD("copl(%p):send next track params in gapless", out);
3435 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3436 out->send_next_track_params = false;
3437 out->is_compr_metadata_avail = false;
3438 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003439 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303440 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303441 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003442
Ashish Jain83a6cc22016-06-28 14:34:17 +05303443 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303444 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303445 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303446 pthread_mutex_unlock(&out->lock);
3447 return -EINVAL;
3448 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303449 audio_format_t dst_format = out->hal_op_format;
3450 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303451
3452 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3453 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3454
Ashish Jain83a6cc22016-06-28 14:34:17 +05303455 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303456 dst_format,
3457 buffer,
3458 src_format,
3459 frames);
3460
Ashish Jain83a6cc22016-06-28 14:34:17 +05303461 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303462 bytes_to_write);
3463
3464 /*Convert written bytes in audio flinger format*/
3465 if (ret > 0)
3466 ret = ((ret * format_to_bitwidth_table[out->format]) /
3467 format_to_bitwidth_table[dst_format]);
3468 }
3469 } else
3470 ret = compress_write(out->compr, buffer, bytes);
3471
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303472 if (ret < 0)
3473 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303474 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303475 /*msg to cb thread only if non blocking write is enabled*/
3476 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303477 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003478 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303479 } else if (-ENETRESET == ret) {
3480 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303481 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05303482 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05303483 out_on_error(&out->stream.common);
Naresh Tanniru80659832014-06-04 18:17:56 +05303484 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003485 }
Ashish Jain5106d362016-05-11 19:23:33 +05303486 if ( ret == (ssize_t)bytes && !out->non_blocking)
3487 out->written += bytes;
3488
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303489 /* Call compr start only when non-zero bytes of data is there to be rendered */
3490 if (!out->playback_started && ret > 0) {
3491 int status = compress_start(out->compr);
3492 if (status < 0) {
3493 ret = status;
3494 ALOGE("%s: compr start failed with err %d", __func__, errno);
3495 goto exit;
3496 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003497 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003498 out->playback_started = 1;
3499 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003500
3501 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3502 popcount(out->channel_mask),
3503 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003504 }
3505 pthread_mutex_unlock(&out->lock);
3506 return ret;
3507 } else {
3508 if (out->pcm) {
3509 if (out->muted)
3510 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003511
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303512 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003513
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003514 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003515
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003516 if (out->config.rate)
3517 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3518 out->config.rate;
3519
3520 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3521
3522 request_out_focus(out, ns);
3523
3524 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003525 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003526 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303527 out->convert_buffer != NULL) {
3528
3529 memcpy_by_audio_format(out->convert_buffer,
3530 out->hal_op_format,
3531 buffer,
3532 out->hal_ip_format,
3533 out->config.period_size * out->config.channels);
3534
3535 ret = pcm_write(out->pcm, out->convert_buffer,
3536 (out->config.period_size *
3537 out->config.channels *
3538 format_to_bitwidth_table[out->hal_op_format]));
3539 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05303540 /*
3541 * To avoid underrun in DSP when the application is not pumping
3542 * data at required rate, check for the no. of bytes and ignore
3543 * pcm_write if it is less than actual buffer size.
3544 * It is a work around to a change in compress VOIP driver.
3545 */
3546 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
3547 bytes < (out->config.period_size * out->config.channels *
3548 audio_bytes_per_sample(out->format))) {
3549 size_t voip_buf_size =
3550 out->config.period_size * out->config.channels *
3551 audio_bytes_per_sample(out->format);
3552 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
3553 __func__, bytes, voip_buf_size);
3554 usleep(((uint64_t)voip_buf_size - bytes) *
3555 1000000 / audio_stream_out_frame_size(stream) /
3556 out_get_sample_rate(&out->stream.common));
3557 ret = 0;
3558 } else
3559 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303560 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003561
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003562 release_out_focus(out);
3563
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303564 if (ret < 0)
3565 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303566 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3567 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3568 else
3569 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003570 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571 }
3572
3573exit:
Naresh Tanniru4c630392014-05-12 01:05:52 +05303574 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303575 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303576 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577 pthread_mutex_unlock(&out->lock);
3578
3579 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003580 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003581 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303582 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303583 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303584 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303585 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303586 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303587 out->standby = true;
3588 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303589 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303590 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3591 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3592 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003593 }
3594 return bytes;
3595}
3596
3597static int out_get_render_position(const struct audio_stream_out *stream,
3598 uint32_t *dsp_frames)
3599{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003600 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08003601
3602 if (dsp_frames == NULL)
3603 return -EINVAL;
3604
3605 *dsp_frames = 0;
3606 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003607 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303608
3609 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3610 * this operation and adev_close_output_stream(where out gets reset).
3611 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303612 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303613 *dsp_frames = get_actual_pcm_frames_rendered(out);
3614 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3615 return 0;
3616 }
3617
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003618 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303619 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303620 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003621 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303622 if (ret < 0)
3623 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003624 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303625 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003626 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303627 if (-ENETRESET == ret) {
3628 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303629 out->card_status = CARD_STATUS_OFFLINE;
3630 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303631 } else if(ret < 0) {
3632 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303633 ret = -EINVAL;
3634 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303635 /*
3636 * Handle corner case where compress session is closed during SSR
3637 * and timestamp is queried
3638 */
3639 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303640 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303641 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303642 ret = 0;
Naresh Tanniru80659832014-06-04 18:17:56 +05303643 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303644 pthread_mutex_unlock(&out->lock);
3645 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08003646 } else if (audio_is_linear_pcm(out->format)) {
3647 *dsp_frames = out->written;
3648 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003649 } else
3650 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651}
3652
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003653static int out_add_audio_effect(const struct audio_stream *stream __unused,
3654 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655{
3656 return 0;
3657}
3658
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003659static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3660 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003661{
3662 return 0;
3663}
3664
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003665static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3666 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303668 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669}
3670
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003671static int out_get_presentation_position(const struct audio_stream_out *stream,
3672 uint64_t *frames, struct timespec *timestamp)
3673{
3674 struct stream_out *out = (struct stream_out *)stream;
3675 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003676 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003677
Ashish Jain5106d362016-05-11 19:23:33 +05303678 /* below piece of code is not guarded against any lock because audioFliner serializes
3679 * this operation and adev_close_output_stream( where out gets reset).
3680 */
3681 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303682 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303683 *frames = get_actual_pcm_frames_rendered(out);
3684 /* this is the best we can do */
3685 clock_gettime(CLOCK_MONOTONIC, timestamp);
3686 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3687 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3688 return 0;
3689 }
3690
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003691 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003692
Ashish Jain5106d362016-05-11 19:23:33 +05303693 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3694 ret = compress_get_tstamp(out->compr, &dsp_frames,
3695 &out->sample_rate);
3696 ALOGVV("%s rendered frames %ld sample_rate %d",
3697 __func__, dsp_frames, out->sample_rate);
3698 *frames = dsp_frames;
3699 if (ret < 0)
3700 ret = -errno;
3701 if (-ENETRESET == ret) {
3702 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303703 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05303704 ret = -EINVAL;
3705 } else
3706 ret = 0;
3707 /* this is the best we can do */
3708 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003709 } else {
3710 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003711 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003712 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3713 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003714 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003715 // This adjustment accounts for buffering after app processor.
3716 // It is based on estimated DSP latency per use case, rather than exact.
3717 signed_frames -=
3718 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3719
Eric Laurent949a0892013-09-20 09:20:13 -07003720 // It would be unusual for this value to be negative, but check just in case ...
3721 if (signed_frames >= 0) {
3722 *frames = signed_frames;
3723 ret = 0;
3724 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003725 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303726 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303727 *frames = out->written;
3728 clock_gettime(CLOCK_MONOTONIC, timestamp);
3729 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003730 }
3731 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003732 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003733 return ret;
3734}
3735
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003736static int out_set_callback(struct audio_stream_out *stream,
3737 stream_callback_t callback, void *cookie)
3738{
3739 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003740 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003741
3742 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003743 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003744 out->client_callback = callback;
3745 out->client_cookie = cookie;
3746 if (out->adsp_hdlr_stream_handle) {
3747 ret = audio_extn_adsp_hdlr_stream_set_callback(
3748 out->adsp_hdlr_stream_handle,
3749 callback,
3750 cookie);
3751 if (ret)
3752 ALOGW("%s:adsp hdlr callback registration failed %d",
3753 __func__, ret);
3754 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003755 pthread_mutex_unlock(&out->lock);
3756 return 0;
3757}
3758
3759static int out_pause(struct audio_stream_out* stream)
3760{
3761 struct stream_out *out = (struct stream_out *)stream;
3762 int status = -ENOSYS;
3763 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003764 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003765 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003766 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003767 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303768 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05303769 status = compress_pause(out->compr);
3770
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003771 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003772
Mingming Yin21854652016-04-13 11:54:02 -07003773 if (audio_extn_passthru_is_active()) {
3774 ALOGV("offload use case, pause passthru");
3775 audio_extn_passthru_on_pause(out);
3776 }
3777
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303778 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003779 audio_extn_dts_notify_playback_state(out->usecase, 0,
3780 out->sample_rate, popcount(out->channel_mask),
3781 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003782 }
3783 pthread_mutex_unlock(&out->lock);
3784 }
3785 return status;
3786}
3787
3788static int out_resume(struct audio_stream_out* stream)
3789{
3790 struct stream_out *out = (struct stream_out *)stream;
3791 int status = -ENOSYS;
3792 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003793 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003794 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003795 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003796 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003797 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303798 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303799 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003800 }
3801 if (!status) {
3802 out->offload_state = OFFLOAD_STATE_PLAYING;
3803 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303804 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003805 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3806 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003807 }
3808 pthread_mutex_unlock(&out->lock);
3809 }
3810 return status;
3811}
3812
3813static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3814{
3815 struct stream_out *out = (struct stream_out *)stream;
3816 int status = -ENOSYS;
3817 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003818 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003819 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003820 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3821 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3822 else
3823 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3824 pthread_mutex_unlock(&out->lock);
3825 }
3826 return status;
3827}
3828
3829static int out_flush(struct audio_stream_out* stream)
3830{
3831 struct stream_out *out = (struct stream_out *)stream;
3832 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003833 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003834 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003835 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003836 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3837 stop_compressed_output_l(out);
3838 out->written = 0;
3839 } else {
3840 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3841 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003842 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003843 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003844 return 0;
3845 }
3846 return -ENOSYS;
3847}
3848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849/** audio_stream_in implementation **/
3850static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3851{
3852 struct stream_in *in = (struct stream_in *)stream;
3853
3854 return in->config.rate;
3855}
3856
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003857static int in_set_sample_rate(struct audio_stream *stream __unused,
3858 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859{
3860 return -ENOSYS;
3861}
3862
3863static size_t in_get_buffer_size(const struct audio_stream *stream)
3864{
3865 struct stream_in *in = (struct stream_in *)stream;
3866
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003867 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3868 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003869 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
3870 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 -07003871 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3872 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303873 else if(audio_extn_cin_attached_usecase(in->usecase))
3874 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003875
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003876 return in->config.period_size * in->af_period_multiplier *
3877 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878}
3879
3880static uint32_t in_get_channels(const struct audio_stream *stream)
3881{
3882 struct stream_in *in = (struct stream_in *)stream;
3883
3884 return in->channel_mask;
3885}
3886
3887static audio_format_t in_get_format(const struct audio_stream *stream)
3888{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003889 struct stream_in *in = (struct stream_in *)stream;
3890
3891 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003892}
3893
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003894static int in_set_format(struct audio_stream *stream __unused,
3895 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003896{
3897 return -ENOSYS;
3898}
3899
3900static int in_standby(struct audio_stream *stream)
3901{
3902 struct stream_in *in = (struct stream_in *)stream;
3903 struct audio_device *adev = in->dev;
3904 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303905 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3906 stream, in->usecase, use_case_table[in->usecase]);
3907
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003908 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003909 if (!in->standby && in->is_st_session) {
3910 ALOGD("%s: sound trigger pcm stop lab", __func__);
3911 audio_extn_sound_trigger_stop_lab(in);
3912 in->standby = 1;
3913 }
3914
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003916 if (adev->adm_deregister_stream)
3917 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3918
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003919 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003920 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003921 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3922 voice_extn_compress_voip_close_input_stream(stream);
3923 ALOGD("VOIP input entered standby");
3924 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303925 if (audio_extn_cin_attached_usecase(in->usecase))
3926 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003927 if (in->pcm) {
3928 pcm_close(in->pcm);
3929 in->pcm = NULL;
3930 }
3931 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003932 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003933 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003934 }
3935 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003936 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003937 return status;
3938}
3939
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003940static int in_dump(const struct audio_stream *stream __unused,
3941 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942{
3943 return 0;
3944}
3945
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303946static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3947{
3948 if (!stream || !parms)
3949 return;
3950
3951 struct stream_in *in = (struct stream_in *)stream;
3952 struct audio_device *adev = in->dev;
3953
3954 card_status_t status;
3955 int card;
3956 if (parse_snd_card_status(parms, &card, &status) < 0)
3957 return;
3958
3959 pthread_mutex_lock(&adev->lock);
3960 bool valid_cb = (card == adev->snd_card);
3961 pthread_mutex_unlock(&adev->lock);
3962
3963 if (!valid_cb)
3964 return;
3965
3966 lock_input_stream(in);
3967 if (in->card_status != status)
3968 in->card_status = status;
3969 pthread_mutex_unlock(&in->lock);
3970
3971 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3972 use_case_table[in->usecase],
3973 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3974
3975 // a better solution would be to report error back to AF and let
3976 // it put the stream to standby
3977 if (status == CARD_STATUS_OFFLINE)
3978 in_standby(&in->stream.common);
3979
3980 return;
3981}
3982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003983static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3984{
3985 struct stream_in *in = (struct stream_in *)stream;
3986 struct audio_device *adev = in->dev;
3987 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003988 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003989 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003990
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303991 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003992 parms = str_parms_create_str(kvpairs);
3993
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303994 if (!parms)
3995 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003996 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003997 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003998
3999 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4000 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004001 val = atoi(value);
4002 /* no audio source uses val == 0 */
4003 if ((in->source != val) && (val != 0)) {
4004 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004005 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4006 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4007 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004008 (in->config.rate == 8000 || in->config.rate == 16000 ||
4009 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004010 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004011 err = voice_extn_compress_voip_open_input_stream(in);
4012 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004013 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004014 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004015 }
4016 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004017 }
4018 }
4019
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004020 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4021 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004022 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004023 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024 in->device = val;
4025 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004026 if (!in->standby && !in->is_st_session) {
4027 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07004028 if (adev->adm_on_routing_change)
4029 adev->adm_on_routing_change(adev->adm_data,
4030 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004031 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004032 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004033 }
4034 }
4035
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304036 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4037 if (err >= 0) {
4038 strlcpy(in->profile, value, sizeof(in->profile));
4039 ALOGV("updating stream profile with value '%s'", in->profile);
4040 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4041 &adev->streams_input_cfg_list,
4042 in->device, in->flags, in->format,
4043 in->sample_rate, in->bit_width,
4044 in->profile, &in->app_type_cfg);
4045 }
4046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004047 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004048 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004049
4050 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304051error:
Eric Laurent994a6932013-07-17 11:51:42 -07004052 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004053 return ret;
4054}
4055
4056static char* in_get_parameters(const struct audio_stream *stream,
4057 const char *keys)
4058{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004059 struct stream_in *in = (struct stream_in *)stream;
4060 struct str_parms *query = str_parms_create_str(keys);
4061 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004062 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004063
4064 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004065 if (reply) {
4066 str_parms_destroy(reply);
4067 }
4068 if (query) {
4069 str_parms_destroy(query);
4070 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004071 ALOGE("in_get_parameters: failed to create query or reply");
4072 return NULL;
4073 }
4074
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004075 ALOGV("%s: enter: keys - %s", __func__, keys);
4076
4077 voice_extn_in_get_parameters(in, query, reply);
4078
4079 str = str_parms_to_str(reply);
4080 str_parms_destroy(query);
4081 str_parms_destroy(reply);
4082
4083 ALOGV("%s: exit: returns - %s", __func__, str);
4084 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085}
4086
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004087static int in_set_gain(struct audio_stream_in *stream __unused,
4088 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089{
4090 return 0;
4091}
4092
4093static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4094 size_t bytes)
4095{
4096 struct stream_in *in = (struct stream_in *)stream;
4097 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304098 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304099 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004100
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004101 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304102
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004103 if (in->is_st_session) {
4104 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
4105 /* Read from sound trigger HAL */
4106 audio_extn_sound_trigger_read(in, buffer, bytes);
4107 pthread_mutex_unlock(&in->lock);
4108 return bytes;
4109 }
4110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004111 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004112 pthread_mutex_lock(&adev->lock);
4113 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
4114 ret = voice_extn_compress_voip_start_input_stream(in);
4115 else
4116 ret = start_input_stream(in);
4117 pthread_mutex_unlock(&adev->lock);
4118 if (ret != 0) {
4119 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004120 }
4121 in->standby = 0;
4122 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004123
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004124 // what's the duration requested by the client?
4125 long ns = 0;
4126
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304127 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004128 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4129 in->config.rate;
4130
4131 request_in_focus(in, ns);
4132 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004133
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304134 if (audio_extn_cin_attached_usecase(in->usecase)) {
4135 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
4136 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304137 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004138 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304139 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07004140 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004141 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004142 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304143 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004144 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304145 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4146 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4147 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
4148 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304149 ret = -EINVAL;
4150 goto exit;
4151 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304152 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304153 ret = -errno;
4154 }
4155 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304156 /* bytes read is always set to bytes for non compress usecases */
4157 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004158 }
4159
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004160 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004161
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162 /*
4163 * Instead of writing zeroes here, we could trust the hardware
4164 * to always provide zeroes when muted.
4165 */
Pavan Chikkala63964842014-12-04 10:48:28 +05304166 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
4167 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004168 memset(buffer, 0, bytes);
4169
4170exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004171 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304172 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004173 pthread_mutex_unlock(&in->lock);
4174
4175 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304176 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304177 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304178 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304179 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304180 in->standby = true;
4181 }
Sharad Sangled17c9122017-03-20 15:58:52 +05304182 if (!audio_extn_cin_attached_usecase(in->usecase)) {
4183 bytes_read = bytes;
4184 memset(buffer, 0, bytes);
4185 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004186 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004187 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05304188 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05304189 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004190 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304191 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004192}
4193
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004194static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004195{
4196 return 0;
4197}
4198
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004199static int add_remove_audio_effect(const struct audio_stream *stream,
4200 effect_handle_t effect,
4201 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004202{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004203 struct stream_in *in = (struct stream_in *)stream;
4204 int status = 0;
4205 effect_descriptor_t desc;
4206
4207 status = (*effect)->get_descriptor(effect, &desc);
4208 if (status != 0)
4209 return status;
4210
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004211 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004212 pthread_mutex_lock(&in->dev->lock);
4213 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4214 in->enable_aec != enable &&
4215 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4216 in->enable_aec = enable;
4217 if (!in->standby)
4218 select_devices(in->dev, in->usecase);
4219 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08004220 if (in->enable_ns != enable &&
4221 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4222 in->enable_ns = enable;
4223 if (!in->standby)
4224 select_devices(in->dev, in->usecase);
4225 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004226 pthread_mutex_unlock(&in->dev->lock);
4227 pthread_mutex_unlock(&in->lock);
4228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004229 return 0;
4230}
4231
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004232static int in_add_audio_effect(const struct audio_stream *stream,
4233 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004234{
Eric Laurent994a6932013-07-17 11:51:42 -07004235 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004236 return add_remove_audio_effect(stream, effect, true);
4237}
4238
4239static int in_remove_audio_effect(const struct audio_stream *stream,
4240 effect_handle_t effect)
4241{
Eric Laurent994a6932013-07-17 11:51:42 -07004242 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004243 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004244}
4245
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304246int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247 audio_io_handle_t handle,
4248 audio_devices_t devices,
4249 audio_output_flags_t flags,
4250 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004251 struct audio_stream_out **stream_out,
4252 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004253{
4254 struct audio_device *adev = (struct audio_device *)dev;
4255 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304256 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004257 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004258 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004259
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004260 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304261
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004262 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4263
Mingming Yin3a941d42016-02-17 18:08:05 -08004264 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
4265 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304266 devices, flags, &out->stream);
4267
4268
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004269 if (!out) {
4270 return -ENOMEM;
4271 }
4272
Haynes Mathew George204045b2015-02-25 20:32:03 -08004273 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004274 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08004275 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4276
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004277 if (devices == AUDIO_DEVICE_NONE)
4278 devices = AUDIO_DEVICE_OUT_SPEAKER;
4279
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004280 out->flags = flags;
4281 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004282 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004283 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004284 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05304285 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004286 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07004287 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004288 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08004289 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304290 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304291 out->started = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004292
Mingming Yin3a941d42016-02-17 18:08:05 -08004293 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4294 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
4295 pthread_mutex_lock(&adev->lock);
4296 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
4297 ret = read_hdmi_sink_caps(out);
4298 pthread_mutex_unlock(&adev->lock);
4299 if (ret != 0) {
4300 if (ret == -ENOSYS) {
4301 /* ignore and go with default */
4302 ret = 0;
4303 } else {
4304 ALOGE("error reading hdmi sink caps");
4305 goto error_open;
4306 }
4307 }
4308 }
4309
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310 /* Init use case and pcm_config */
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004311#ifndef COMPRESS_VOIP_ENABLED
4312 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4313 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
4314 out->sample_rate == 32000 || out->sample_rate == 48000)) {
4315 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
4316 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
4317 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4318
4319 out->config = default_pcm_config_voip_copp;
4320 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
4321 out->config.rate = out->sample_rate;
4322
4323#else
Dhananjay Kumarac341582017-02-23 23:42:25 +05304324 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004325 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08004326 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004327 ret = voice_extn_compress_voip_open_output_stream(out);
4328 if (ret != 0) {
4329 ALOGE("%s: Compress voip output cannot be opened, error:%d",
4330 __func__, ret);
4331 goto error_open;
4332 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004333#endif
vivek mehta0ea887a2015-08-26 14:01:20 -07004334 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304335 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304336 pthread_mutex_lock(&adev->lock);
4337 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4338 pthread_mutex_unlock(&adev->lock);
4339
4340 // reject offload during card offline to allow
4341 // fallback to s/w paths
4342 if (offline) {
4343 ret = -ENODEV;
4344 goto error_open;
4345 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004346
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004347 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4348 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4349 ALOGE("%s: Unsupported Offload information", __func__);
4350 ret = -EINVAL;
4351 goto error_open;
4352 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004353
Mingming Yin3a941d42016-02-17 18:08:05 -08004354 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004355 if(config->offload_info.format == 0)
4356 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004357 if (config->offload_info.sample_rate == 0)
4358 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004359 }
4360
Mingming Yin90310102013-11-13 16:57:00 -08004361 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304362 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004363 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004364 ret = -EINVAL;
4365 goto error_open;
4366 }
4367
Ben Romberger0f8c87b2017-05-24 17:41:11 -07004368 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
4369 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
4370 (audio_extn_passthru_is_passthrough_stream(out)) &&
4371 !((config->sample_rate == 48000) ||
4372 (config->sample_rate == 96000) ||
4373 (config->sample_rate == 192000))) {
4374 ALOGE("%s: Unsupported sample rate %d for audio format %x",
4375 __func__, config->sample_rate, config->offload_info.format);
4376 ret = -EINVAL;
4377 goto error_open;
4378 }
4379
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004380 out->compr_config.codec = (struct snd_codec *)
4381 calloc(1, sizeof(struct snd_codec));
4382
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004383 if (!out->compr_config.codec) {
4384 ret = -ENOMEM;
4385 goto error_open;
4386 }
4387
Dhananjay Kumarac341582017-02-23 23:42:25 +05304388 out->stream.pause = out_pause;
4389 out->stream.resume = out_resume;
4390 out->stream.flush = out_flush;
4391 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004392 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004393 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304394 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004395 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304396 } else {
4397 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4398 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004399 }
vivek mehta446c3962015-09-14 10:57:35 -07004400
4401 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004402 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4403 config->format == 0 && config->sample_rate == 0 &&
4404 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004405 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004406 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4407 } else {
4408 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4409 ret = -EEXIST;
4410 goto error_open;
4411 }
vivek mehta446c3962015-09-14 10:57:35 -07004412 }
4413
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004414 if (config->offload_info.channel_mask)
4415 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004416 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004417 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004418 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004419 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304420 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004421 ret = -EINVAL;
4422 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004423 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004424
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004425 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004426 out->sample_rate = config->offload_info.sample_rate;
4427
Mingming Yin3ee55c62014-08-04 14:23:35 -07004428 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004429
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304430 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4431 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4432 audio_extn_dolby_send_ddp_endp_params(adev);
4433 audio_extn_dolby_set_dmid(adev);
4434 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004435
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004436 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004437 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004438 out->compr_config.codec->bit_rate =
4439 config->offload_info.bit_rate;
4440 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304441 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004442 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304443 /* Update bit width only for non passthrough usecases.
4444 * For passthrough usecases, the output will always be opened @16 bit
4445 */
4446 if (!audio_extn_passthru_is_passthrough_stream(out))
4447 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304448
4449 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4450 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
4451 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
4452
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004453 /*TODO: Do we need to change it for passthrough */
4454 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004455
Manish Dewangana6fc5442015-08-24 20:30:31 +05304456 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4457 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304458 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304459 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304460 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4461 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304462
4463 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4464 AUDIO_FORMAT_PCM) {
4465
4466 /*Based on platform support, configure appropriate alsa format for corresponding
4467 *hal input format.
4468 */
4469 out->compr_config.codec->format = hal_format_to_alsa(
4470 config->offload_info.format);
4471
Ashish Jain83a6cc22016-06-28 14:34:17 +05304472 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304473 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304474 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304475
Dhananjay Kumarac341582017-02-23 23:42:25 +05304476 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304477 *hal input format and alsa format might differ based on platform support.
4478 */
4479 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304480 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304481
4482 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4483
4484 /* Check if alsa session is configured with the same format as HAL input format,
4485 * if not then derive correct fragment size needed to accomodate the
4486 * conversion of HAL input format to alsa format.
4487 */
4488 audio_extn_utils_update_direct_pcm_fragment_size(out);
4489
4490 /*if hal input and output fragment size is different this indicates HAL input format is
4491 *not same as the alsa format
4492 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304493 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304494 /*Allocate a buffer to convert input data to the alsa configured format.
4495 *size of convert buffer is equal to the size required to hold one fragment size
4496 *worth of pcm data, this is because flinger does not write more than fragment_size
4497 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304498 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4499 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304500 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4501 ret = -ENOMEM;
4502 goto error_open;
4503 }
4504 }
4505 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4506 out->compr_config.fragment_size =
4507 audio_extn_passthru_get_buffer_size(&config->offload_info);
4508 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4509 } else {
4510 out->compr_config.fragment_size =
4511 platform_get_compress_offload_buffer_size(&config->offload_info);
4512 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4513 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004514
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304515 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4516 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
4517 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07004518 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304519 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004520
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304521 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4522 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4523 }
4524
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004525 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4526 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004527
Manish Dewangan69426c82017-01-30 17:35:36 +05304528 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
4529 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
4530 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
4531 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4532 out->render_mode = RENDER_MODE_AUDIO_MASTER;
4533 } else {
4534 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
4535 }
Alexy Josephaa54c872014-12-03 02:46:47 -08004536
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05304537 memset(&out->channel_map_param, 0,
4538 sizeof(struct audio_out_channel_map_param));
4539
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004540 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304541 out->send_next_track_params = false;
4542 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004543 out->offload_state = OFFLOAD_STATE_IDLE;
4544 out->playback_started = 0;
4545
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004546 audio_extn_dts_create_state_notifier_node(out->usecase);
4547
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004548 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4549 __func__, config->offload_info.version,
4550 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304551
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304552 /* Check if DSD audio format is supported in codec
4553 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304554 */
4555
4556 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304557 (!platform_check_codec_dsd_support(adev->platform) ||
4558 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304559 ret = -EINVAL;
4560 goto error_open;
4561 }
4562
Ashish Jain5106d362016-05-11 19:23:33 +05304563 /* Disable gapless if any of the following is true
4564 * passthrough playback
4565 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304566 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304567 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304568 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304569 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07004570 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304571 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304572 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304573 check_and_set_gapless_mode(adev, false);
4574 } else
4575 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004576
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304577 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004578 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4579 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304580 if (config->format == AUDIO_FORMAT_DSD) {
4581 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4582 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4583 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004584
4585 create_offload_callback_thread(out);
4586
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004587 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304588 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004589 if (ret != 0) {
4590 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4591 __func__, ret);
4592 goto error_open;
4593 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004594 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4595 if (config->sample_rate == 0)
4596 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4597 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4598 config->sample_rate != 8000) {
4599 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4600 ret = -EINVAL;
4601 goto error_open;
4602 }
4603 out->sample_rate = config->sample_rate;
4604 out->config.rate = config->sample_rate;
4605 if (config->format == AUDIO_FORMAT_DEFAULT)
4606 config->format = AUDIO_FORMAT_PCM_16_BIT;
4607 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4608 config->format = AUDIO_FORMAT_PCM_16_BIT;
4609 ret = -EINVAL;
4610 goto error_open;
4611 }
4612 out->format = config->format;
4613 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4614 out->config = pcm_config_afe_proxy_playback;
4615 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004616 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304617 unsigned int channels = 0;
4618 /*Update config params to default if not set by the caller*/
4619 if (config->sample_rate == 0)
4620 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4621 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4622 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4623 if (config->format == AUDIO_FORMAT_DEFAULT)
4624 config->format = AUDIO_FORMAT_PCM_16_BIT;
4625
4626 channels = audio_channel_count_from_out_mask(out->channel_mask);
4627
Ashish Jain83a6cc22016-06-28 14:34:17 +05304628 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4629 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004630 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4631 out->flags);
4632 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304633 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4634 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4635 out->config = pcm_config_low_latency;
4636 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4637 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4638 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304639 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4640 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4641 if (out->config.period_size <= 0) {
4642 ALOGE("Invalid configuration period size is not valid");
4643 ret = -EINVAL;
4644 goto error_open;
4645 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304646 } else {
4647 /* primary path is the default path selected if no other outputs are available/suitable */
4648 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4649 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4650 }
4651 out->hal_ip_format = format = out->format;
4652 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4653 out->hal_op_format = pcm_format_to_hal(out->config.format);
4654 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4655 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004656 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304657 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304658 if (out->hal_ip_format != out->hal_op_format) {
4659 uint32_t buffer_size = out->config.period_size *
4660 format_to_bitwidth_table[out->hal_op_format] *
4661 out->config.channels;
4662 out->convert_buffer = calloc(1, buffer_size);
4663 if (out->convert_buffer == NULL){
4664 ALOGE("Allocation failed for convert buffer for size %d",
4665 out->compr_config.fragment_size);
4666 ret = -ENOMEM;
4667 goto error_open;
4668 }
4669 ALOGD("Convert buffer allocated of size %d", buffer_size);
4670 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004671 }
4672
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004673 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4674 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304675
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004676 /* TODO remove this hardcoding and check why width is zero*/
4677 if (out->bit_width == 0)
4678 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304679 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004680 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304681 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304682 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304683 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004684 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4685 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4686 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004687 if(adev->primary_output == NULL)
4688 adev->primary_output = out;
4689 else {
4690 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004691 ret = -EEXIST;
4692 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004693 }
4694 }
4695
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004696 /* Check if this usecase is already existing */
4697 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004698 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4699 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004700 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004701 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004702 ret = -EEXIST;
4703 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004704 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004706 pthread_mutex_unlock(&adev->lock);
4707
4708 out->stream.common.get_sample_rate = out_get_sample_rate;
4709 out->stream.common.set_sample_rate = out_set_sample_rate;
4710 out->stream.common.get_buffer_size = out_get_buffer_size;
4711 out->stream.common.get_channels = out_get_channels;
4712 out->stream.common.get_format = out_get_format;
4713 out->stream.common.set_format = out_set_format;
4714 out->stream.common.standby = out_standby;
4715 out->stream.common.dump = out_dump;
4716 out->stream.common.set_parameters = out_set_parameters;
4717 out->stream.common.get_parameters = out_get_parameters;
4718 out->stream.common.add_audio_effect = out_add_audio_effect;
4719 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4720 out->stream.get_latency = out_get_latency;
4721 out->stream.set_volume = out_set_volume;
4722 out->stream.write = out_write;
4723 out->stream.get_render_position = out_get_render_position;
4724 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004725 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004726
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004727 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004728 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004729 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004730 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004731
4732 config->format = out->stream.common.get_format(&out->stream.common);
4733 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4734 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4735
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304736 /*
4737 By locking output stream before registering, we allow the callback
4738 to update stream's state only after stream's initial state is set to
4739 adev state.
4740 */
4741 lock_output_stream(out);
4742 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4743 pthread_mutex_lock(&adev->lock);
4744 out->card_status = adev->card_status;
4745 pthread_mutex_unlock(&adev->lock);
4746 pthread_mutex_unlock(&out->lock);
4747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004748 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304749 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004750 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004751
4752 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4753 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4754 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004755 /* setup a channel for client <--> adsp communication for stream events */
4756 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07004757 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
4758 (audio_extn_ip_hdlr_intf_supported(config->format))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004759 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
4760 out->usecase, PCM_PLAYBACK);
4761 hdlr_stream_cfg.flags = out->flags;
4762 hdlr_stream_cfg.type = PCM_PLAYBACK;
4763 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
4764 &hdlr_stream_cfg);
4765 if (ret) {
4766 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
4767 out->adsp_hdlr_stream_handle = NULL;
4768 }
4769 }
Naresh Tanniru85819452017-05-04 18:55:45 -07004770 if (audio_extn_ip_hdlr_intf_supported(config->format)) {
4771 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL);
4772 if (ret < 0) {
4773 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
4774 out->ip_hdlr_handle = NULL;
4775 }
4776 }
Eric Laurent994a6932013-07-17 11:51:42 -07004777 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004778 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004779
4780error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304781 if (out->convert_buffer)
4782 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004783 free(out);
4784 *stream_out = NULL;
4785 ALOGD("%s: exit: ret %d", __func__, ret);
4786 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004787}
4788
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304789void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004790 struct audio_stream_out *stream)
4791{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004792 struct stream_out *out = (struct stream_out *)stream;
4793 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004794 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004795
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304796 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4797
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304798 // must deregister from sndmonitor first to prevent races
4799 // between the callback and close_stream
4800 audio_extn_snd_mon_unregister_listener(out);
4801
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004802 /* close adsp hdrl session before standby */
4803 if (out->adsp_hdlr_stream_handle) {
4804 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
4805 if (ret)
4806 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
4807 out->adsp_hdlr_stream_handle = NULL;
4808 }
4809
Naresh Tanniru85819452017-05-04 18:55:45 -07004810 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
4811 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
4812 out->ip_hdlr_handle = NULL;
4813 }
4814
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004815 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304816 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004817 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304818 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304819 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004820 if(ret != 0)
4821 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4822 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004823 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004824 out_standby(&stream->common);
4825
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004826 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004827 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004828 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004829 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004830 if (out->compr_config.codec != NULL)
4831 free(out->compr_config.codec);
4832 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004833
Ashish Jain83a6cc22016-06-28 14:34:17 +05304834 if (out->convert_buffer != NULL) {
4835 free(out->convert_buffer);
4836 out->convert_buffer = NULL;
4837 }
4838
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004839 if (adev->voice_tx_output == out)
4840 adev->voice_tx_output = NULL;
4841
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304842 if (adev->primary_output == out)
4843 adev->primary_output = NULL;
4844
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004845 pthread_cond_destroy(&out->cond);
4846 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004847 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004848 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004849}
4850
4851static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4852{
4853 struct audio_device *adev = (struct audio_device *)dev;
4854 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004855 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004856 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004857 int ret;
4858 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004859
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004860 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004861 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004862
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304863 if (!parms)
4864 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304865
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304866 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
4867 if (ret >= 0) {
4868 /* When set to false, HAL should disable EC and NS */
4869 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4870 adev->bt_sco_on = true;
4871 else
4872 adev->bt_sco_on = false;
4873 }
4874
Naresh Tanniru4c630392014-05-12 01:05:52 +05304875 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004876 status = voice_set_parameters(adev, parms);
4877 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004878 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004879
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004880 status = platform_set_parameters(adev->platform, parms);
4881 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004882 goto done;
4883
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004884 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4885 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004886 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004887 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4888 adev->bluetooth_nrec = true;
4889 else
4890 adev->bluetooth_nrec = false;
4891 }
4892
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004893 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4894 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004895 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4896 adev->screen_off = false;
4897 else
4898 adev->screen_off = true;
4899 }
4900
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004901 ret = str_parms_get_int(parms, "rotation", &val);
4902 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004903 bool reverse_speakers = false;
4904 switch(val) {
4905 // FIXME: note that the code below assumes that the speakers are in the correct placement
4906 // relative to the user when the device is rotated 90deg from its default rotation. This
4907 // assumption is device-specific, not platform-specific like this code.
4908 case 270:
4909 reverse_speakers = true;
4910 break;
4911 case 0:
4912 case 90:
4913 case 180:
4914 break;
4915 default:
4916 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004917 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004918 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004919 if (status == 0) {
4920 if (adev->speaker_lr_swap != reverse_speakers) {
4921 adev->speaker_lr_swap = reverse_speakers;
4922 // only update the selected device if there is active pcm playback
4923 struct audio_usecase *usecase;
4924 struct listnode *node;
4925 list_for_each(node, &adev->usecase_list) {
4926 usecase = node_to_item(node, struct audio_usecase, list);
4927 if (usecase->type == PCM_PLAYBACK) {
4928 select_devices(adev, usecase->id);
4929 break;
4930 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004931 }
4932 }
4933 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004934 }
4935
Mingming Yin514a8bc2014-07-29 15:22:21 -07004936 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4937 if (ret >= 0) {
4938 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4939 adev->bt_wb_speech_enabled = true;
4940 else
4941 adev->bt_wb_speech_enabled = false;
4942 }
4943
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004944 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4945 if (ret >= 0) {
4946 val = atoi(value);
4947 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004948 ALOGV("cache new ext disp type and edid");
4949 ret = platform_get_ext_disp_type(adev->platform);
4950 if (ret < 0) {
4951 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004952 status = ret;
4953 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004954 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004955 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004956 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004957 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004958 /*
4959 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4960 * Per AudioPolicyManager, USB device is higher priority than WFD.
4961 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4962 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4963 * starting voice call on USB
4964 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004965 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4966 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004967 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4968 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004969 }
vivek mehta344576a2016-04-12 18:56:03 -07004970 ALOGV("detected USB connect .. disable proxy");
4971 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004972 }
4973 }
4974
4975 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4976 if (ret >= 0) {
4977 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004978 /*
4979 * The HDMI / Displayport disconnect handling has been moved to
4980 * audio extension to ensure that its parameters are not
4981 * invalidated prior to updating sysfs of the disconnect event
4982 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4983 */
4984 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004985 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004986 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4987 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304988 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4989 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004990 }
vivek mehta344576a2016-04-12 18:56:03 -07004991 ALOGV("detected USB disconnect .. enable proxy");
4992 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004993 }
4994 }
4995
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304996 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4997 if (ret >= 0) {
4998 struct audio_usecase *usecase;
4999 struct listnode *node;
5000 list_for_each(node, &adev->usecase_list) {
5001 usecase = node_to_item(node, struct audio_usecase, list);
5002 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07005003 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305004 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08005005
5006 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305007 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08005008 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305009 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305010 //force device switch to re configure encoder
5011 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305012 audio_extn_a2dp_set_handoff_mode(false);
5013 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305014 break;
5015 }
5016 }
5017 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005018
5019 //handle vr audio setparam
5020 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5021 value, sizeof(value));
5022 if (ret >= 0) {
5023 ALOGI("Setting vr mode to be %s", value);
5024 if (!strncmp(value, "true", 4)) {
5025 adev->vr_audio_mode_enabled = true;
5026 ALOGI("Setting vr mode to true");
5027 } else if (!strncmp(value, "false", 5)) {
5028 adev->vr_audio_mode_enabled = false;
5029 ALOGI("Setting vr mode to false");
5030 } else {
5031 ALOGI("wrong vr mode set");
5032 }
5033 }
5034
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305035 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005036done:
5037 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005038 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305039error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005040 ALOGV("%s: exit with code(%d)", __func__, status);
5041 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005042}
5043
5044static char* adev_get_parameters(const struct audio_hw_device *dev,
5045 const char *keys)
5046{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005047 struct audio_device *adev = (struct audio_device *)dev;
5048 struct str_parms *reply = str_parms_create();
5049 struct str_parms *query = str_parms_create_str(keys);
5050 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05305051 char value[256] = {0};
5052 int ret = 0;
5053
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005054 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005055 if (reply) {
5056 str_parms_destroy(reply);
5057 }
5058 if (query) {
5059 str_parms_destroy(query);
5060 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005061 ALOGE("adev_get_parameters: failed to create query or reply");
5062 return NULL;
5063 }
5064
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005065 //handle vr audio getparam
5066
5067 ret = str_parms_get_str(query,
5068 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5069 value, sizeof(value));
5070
5071 if (ret >= 0) {
5072 bool vr_audio_enabled = false;
5073 pthread_mutex_lock(&adev->lock);
5074 vr_audio_enabled = adev->vr_audio_mode_enabled;
5075 pthread_mutex_unlock(&adev->lock);
5076
5077 ALOGI("getting vr mode to %d", vr_audio_enabled);
5078
5079 if (vr_audio_enabled) {
5080 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5081 "true");
5082 goto exit;
5083 } else {
5084 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5085 "false");
5086 goto exit;
5087 }
5088 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005089
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005090 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005091 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08005092 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005093 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05305094 pthread_mutex_unlock(&adev->lock);
5095
Naresh Tannirud7205b62014-06-20 02:54:48 +05305096exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005097 str = str_parms_to_str(reply);
5098 str_parms_destroy(query);
5099 str_parms_destroy(reply);
5100
5101 ALOGV("%s: exit: returns - %s", __func__, str);
5102 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005103}
5104
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005105static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005106{
5107 return 0;
5108}
5109
5110static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5111{
Haynes Mathew George5191a852013-09-11 14:19:36 -07005112 int ret;
5113 struct audio_device *adev = (struct audio_device *)dev;
5114 pthread_mutex_lock(&adev->lock);
5115 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07005116 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005117 pthread_mutex_unlock(&adev->lock);
5118 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005119}
5120
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005121static int adev_set_master_volume(struct audio_hw_device *dev __unused,
5122 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005123{
5124 return -ENOSYS;
5125}
5126
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005127static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5128 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005129{
5130 return -ENOSYS;
5131}
5132
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005133static int adev_set_master_mute(struct audio_hw_device *dev __unused,
5134 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005135{
5136 return -ENOSYS;
5137}
5138
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005139static int adev_get_master_mute(struct audio_hw_device *dev __unused,
5140 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005141{
5142 return -ENOSYS;
5143}
5144
5145static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5146{
5147 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005148
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005149 pthread_mutex_lock(&adev->lock);
5150 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005151 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005152 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08005153 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005154 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07005155 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005156 adev->current_call_output = NULL;
5157 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005158 }
5159 pthread_mutex_unlock(&adev->lock);
5160 return 0;
5161}
5162
5163static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5164{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005165 int ret;
5166
5167 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08005168 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005169 ret = voice_set_mic_mute((struct audio_device *)dev, state);
5170 pthread_mutex_unlock(&adev->lock);
5171
5172 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005173}
5174
5175static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5176{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005177 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005178 return 0;
5179}
5180
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005181static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005182 const struct audio_config *config)
5183{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005184 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005185
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005186 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
5187 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005188}
5189
5190static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005191 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005192 audio_devices_t devices,
5193 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005194 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305195 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005196 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005197 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005198{
5199 struct audio_device *adev = (struct audio_device *)dev;
5200 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005201 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005202 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005203 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305204 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005206 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305207 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
5208 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005209 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305210 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005211
5212 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005213
5214 if (!in) {
5215 ALOGE("failed to allocate input stream");
5216 return -ENOMEM;
5217 }
5218
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305219 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305220 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
5221 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005222 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005223 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005224
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005225 in->stream.common.get_sample_rate = in_get_sample_rate;
5226 in->stream.common.set_sample_rate = in_set_sample_rate;
5227 in->stream.common.get_buffer_size = in_get_buffer_size;
5228 in->stream.common.get_channels = in_get_channels;
5229 in->stream.common.get_format = in_get_format;
5230 in->stream.common.set_format = in_set_format;
5231 in->stream.common.standby = in_standby;
5232 in->stream.common.dump = in_dump;
5233 in->stream.common.set_parameters = in_set_parameters;
5234 in->stream.common.get_parameters = in_get_parameters;
5235 in->stream.common.add_audio_effect = in_add_audio_effect;
5236 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5237 in->stream.set_gain = in_set_gain;
5238 in->stream.read = in_read;
5239 in->stream.get_input_frames_lost = in_get_input_frames_lost;
5240
5241 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005242 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005243 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005244 in->standby = 1;
5245 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005246 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005247 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005248
Dhananjay Kumar973fc362017-01-09 18:48:15 +05305249 in->usecase = USECASE_AUDIO_RECORD;
5250 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
5251 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
5252 is_low_latency = true;
5253#if LOW_LATENCY_CAPTURE_USE_CASE
5254 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
5255#endif
5256 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
5257 }
5258
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005259 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005260 if (in->realtime) {
5261 in->config = pcm_config_audio_capture_rt;
5262 in->sample_rate = in->config.rate;
5263 in->af_period_multiplier = af_period_multiplier;
5264 } else {
5265 in->config = pcm_config_audio_capture;
5266 in->config.rate = config->sample_rate;
5267 in->sample_rate = config->sample_rate;
5268 in->af_period_multiplier = 1;
5269 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305270 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005271
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305272 /* restrict 24 bit capture for unprocessed source only
5273 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
5274 */
5275 if (config->format == AUDIO_FORMAT_DEFAULT) {
5276 config->format = AUDIO_FORMAT_PCM_16_BIT;
5277 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
5278 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
5279 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
5280 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5281 bool ret_error = false;
5282 in->bit_width = 24;
5283 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5284 from HAL is 24_packed and 8_24
5285 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5286 24_packed return error indicating supported format is 24_packed
5287 *> In case of any other source requesting 24 bit or float return error
5288 indicating format supported is 16 bit only.
5289
5290 on error flinger will retry with supported format passed
5291 */
5292 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
5293 (source != AUDIO_SOURCE_CAMCORDER)) {
5294 config->format = AUDIO_FORMAT_PCM_16_BIT;
5295 if (config->sample_rate > 48000)
5296 config->sample_rate = 48000;
5297 ret_error = true;
5298 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
5299 in->config.format = PCM_FORMAT_S24_3LE;
5300 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5301 in->config.format = PCM_FORMAT_S24_LE;
5302 } else {
5303 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
5304 ret_error = true;
5305 }
5306
5307 if (ret_error) {
5308 ret = -EINVAL;
5309 goto err_open;
5310 }
5311 }
5312
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305313 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305314 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
5315 (adev->mode != AUDIO_MODE_IN_CALL)) {
5316 ret = -EINVAL;
5317 goto err_open;
5318 }
5319
5320 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
5321 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005322 if (config->sample_rate == 0)
5323 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5324 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5325 config->sample_rate != 8000) {
5326 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5327 ret = -EINVAL;
5328 goto err_open;
5329 }
5330 if (config->format == AUDIO_FORMAT_DEFAULT)
5331 config->format = AUDIO_FORMAT_PCM_16_BIT;
5332 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5333 config->format = AUDIO_FORMAT_PCM_16_BIT;
5334 ret = -EINVAL;
5335 goto err_open;
5336 }
5337
5338 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5339 in->config = pcm_config_afe_proxy_record;
5340 in->config.channels = channel_count;
5341 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305342 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305343 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
5344 in, config, &channel_mask_updated)) {
5345 if (channel_mask_updated == true) {
5346 ALOGD("%s: return error to retry with updated channel mask (%#x)",
5347 __func__, config->channel_mask);
5348 ret = -EINVAL;
5349 goto err_open;
5350 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05305351 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07005352 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005353 audio_extn_compr_cap_format_supported(config->format) &&
5354 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005355 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305356 } else if (audio_extn_cin_applicable_stream(in)) {
5357 ret = audio_extn_cin_configure_input_stream(in);
5358 if (ret)
5359 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005360 } else {
5361 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005362 if (!in->realtime) {
5363 in->format = config->format;
5364 frame_size = audio_stream_in_frame_size(&in->stream);
5365 buffer_size = get_input_buffer_size(config->sample_rate,
5366 config->format,
5367 channel_count,
5368 is_low_latency);
5369 in->config.period_size = buffer_size / frame_size;
5370 }
5371
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005372#ifndef COMPRESS_VOIP_ENABLED
5373 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5374 (in->config.rate == 8000 || in->config.rate == 16000 ||
5375 in->config.rate == 32000 || in->config.rate == 48000) &&
5376 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5377
5378 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5379 in->config = default_pcm_config_voip_copp;
5380 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5381 in->config.rate = in->sample_rate;
5382#else
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005383 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08005384 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005385 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005386 (in->config.rate == 8000 || in->config.rate == 16000 ||
5387 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005388 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5389 voice_extn_compress_voip_open_input_stream(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005390#endif
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005391 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005392 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005393
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305394 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5395 &adev->streams_input_cfg_list,
5396 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305397 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305398
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005399 /* This stream could be for sound trigger lab,
5400 get sound trigger pcm if present */
5401 audio_extn_sound_trigger_check_and_get_session(in);
5402
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305403 lock_input_stream(in);
5404 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5405 pthread_mutex_lock(&adev->lock);
5406 in->card_status = adev->card_status;
5407 pthread_mutex_unlock(&adev->lock);
5408 pthread_mutex_unlock(&in->lock);
5409
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005410 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005411 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005412 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005413
5414err_open:
5415 free(in);
5416 *stream_in = NULL;
5417 return ret;
5418}
5419
5420static void adev_close_input_stream(struct audio_hw_device *dev,
5421 struct audio_stream_in *stream)
5422{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005423 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005424 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005425 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305426
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305427 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005428
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305429 // must deregister from sndmonitor first to prevent races
5430 // between the callback and close_stream
5431 audio_extn_snd_mon_unregister_listener(stream);
5432
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305433 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005434 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305435
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005436 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305437 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005438 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305439 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005440 if (ret != 0)
5441 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5442 __func__, ret);
5443 } else
5444 in_standby(&stream->common);
5445
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005446 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005447 audio_extn_ssr_deinit();
5448 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005449
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305450 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005451 audio_extn_compr_cap_format_supported(in->config.format))
5452 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305453
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305454 if (audio_extn_cin_attached_usecase(in->usecase))
5455 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005456
Mingming Yinfd7607b2016-01-22 12:48:44 -08005457 if (in->is_st_session) {
5458 ALOGV("%s: sound trigger pcm stop lab", __func__);
5459 audio_extn_sound_trigger_stop_lab(in);
5460 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005461 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005462 return;
5463}
5464
Siddartha Shaik31b530e2017-05-19 15:26:33 +05305465int adev_create_audio_patch(struct audio_hw_device *dev,
5466 unsigned int num_sources,
5467 const struct audio_port_config *sources,
5468 unsigned int num_sinks,
5469 const struct audio_port_config *sinks,
5470 audio_patch_handle_t *handle)
5471{
5472
5473
5474 return audio_extn_hw_loopback_create_audio_patch(dev,
5475 num_sources,
5476 sources,
5477 num_sinks,
5478 sinks,
5479 handle);
5480
5481}
5482
5483int adev_release_audio_patch(struct audio_hw_device *dev,
5484 audio_patch_handle_t handle)
5485{
5486 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
5487}
5488
5489int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
5490{
5491 return audio_extn_hw_loopback_get_audio_port(dev, config);
5492}
5493
5494int adev_set_audio_port_config(struct audio_hw_device *dev,
5495 const struct audio_port_config *config)
5496{
5497 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
5498}
5499
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005500static int adev_dump(const audio_hw_device_t *device __unused,
5501 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005502{
5503 return 0;
5504}
5505
5506static int adev_close(hw_device_t *device)
5507{
5508 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005509
5510 if (!adev)
5511 return 0;
5512
5513 pthread_mutex_lock(&adev_init_lock);
5514
5515 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305516 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005517 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005518 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305519 audio_extn_utils_release_streams_cfg_lists(
5520 &adev->streams_output_cfg_list,
5521 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305522 if (audio_extn_qaf_is_enabled())
5523 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005524 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005525 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005526 free(adev->snd_dev_ref_cnt);
5527 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005528 if (adev->adm_deinit)
5529 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305530 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005531 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305532 audio_extn_snd_mon_deinit();
Siddartha Shaik31b530e2017-05-19 15:26:33 +05305533 audio_extn_loopback_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07005534 free(device);
5535 adev = NULL;
5536 }
5537 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005538
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005539 return 0;
5540}
5541
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005542/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5543 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5544 * just that it _might_ work.
5545 */
5546static int period_size_is_plausible_for_low_latency(int period_size)
5547{
5548 switch (period_size) {
5549 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005550 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005551 case 240:
5552 case 320:
5553 case 480:
5554 return 1;
5555 default:
5556 return 0;
5557 }
5558}
5559
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305560static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
5561{
5562 bool is_snd_card_status = false;
5563 bool is_ext_device_status = false;
5564 char value[32];
5565 int card = -1;
5566 card_status_t status;
5567
5568 if (cookie != adev || !parms)
5569 return;
5570
5571 if (!parse_snd_card_status(parms, &card, &status)) {
5572 is_snd_card_status = true;
5573 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
5574 is_ext_device_status = true;
5575 } else {
5576 // not a valid event
5577 return;
5578 }
5579
5580 pthread_mutex_lock(&adev->lock);
5581 if (card == adev->snd_card || is_ext_device_status) {
5582 if (is_snd_card_status && adev->card_status != status) {
5583 adev->card_status = status;
5584 platform_snd_card_update(adev->platform, status);
5585 audio_extn_fm_set_parameters(adev, parms);
5586 } else if (is_ext_device_status) {
5587 platform_set_parameters(adev->platform, parms);
5588 }
5589 }
5590 pthread_mutex_unlock(&adev->lock);
5591 return;
5592}
5593
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005594static int adev_open(const hw_module_t *module, const char *name,
5595 hw_device_t **device)
5596{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305597 int ret;
5598
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005599 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005600 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5601
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005602 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005603 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005604 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005605 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005606 ALOGD("%s: returning existing instance of adev", __func__);
5607 ALOGD("%s: exit", __func__);
5608 pthread_mutex_unlock(&adev_init_lock);
5609 return 0;
5610 }
5611
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005612 adev = calloc(1, sizeof(struct audio_device));
5613
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005614 if (!adev) {
5615 pthread_mutex_unlock(&adev_init_lock);
5616 return -ENOMEM;
5617 }
5618
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005619 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5620
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05305621#ifdef DYNAMIC_LOG_ENABLED
5622 register_for_dynamic_logging("hal");
5623#endif
5624
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005625 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5626 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5627 adev->device.common.module = (struct hw_module_t *)module;
5628 adev->device.common.close = adev_close;
5629
5630 adev->device.init_check = adev_init_check;
5631 adev->device.set_voice_volume = adev_set_voice_volume;
5632 adev->device.set_master_volume = adev_set_master_volume;
5633 adev->device.get_master_volume = adev_get_master_volume;
5634 adev->device.set_master_mute = adev_set_master_mute;
5635 adev->device.get_master_mute = adev_get_master_mute;
5636 adev->device.set_mode = adev_set_mode;
5637 adev->device.set_mic_mute = adev_set_mic_mute;
5638 adev->device.get_mic_mute = adev_get_mic_mute;
5639 adev->device.set_parameters = adev_set_parameters;
5640 adev->device.get_parameters = adev_get_parameters;
5641 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5642 adev->device.open_output_stream = adev_open_output_stream;
5643 adev->device.close_output_stream = adev_close_output_stream;
5644 adev->device.open_input_stream = adev_open_input_stream;
5645 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05305646 adev->device.create_audio_patch = adev_create_audio_patch;
5647 adev->device.release_audio_patch = adev_release_audio_patch;
5648 adev->device.get_audio_port = adev_get_audio_port;
5649 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005650 adev->device.dump = adev_dump;
5651
5652 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005653 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005654 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005655 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005656 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005657 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005658 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005659 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305660 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005661 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005662 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005663 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005664 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005665 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005666 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305667 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305668 adev->perf_lock_opts[0] = 0x101;
5669 adev->perf_lock_opts[1] = 0x20E;
5670 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005672 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005673 adev->platform = platform_init(adev);
5674 if (!adev->platform) {
5675 free(adev->snd_dev_ref_cnt);
5676 free(adev);
5677 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5678 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005679 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305680 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005681 return -EINVAL;
5682 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005683
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305684 if (audio_extn_qaf_is_enabled()) {
5685 ret = audio_extn_qaf_init(adev);
5686 if (ret < 0) {
5687 free(adev);
5688 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5689 *device = NULL;
5690 pthread_mutex_unlock(&adev_init_lock);
5691 pthread_mutex_destroy(&adev->lock);
5692 return ret;
5693 }
5694
5695 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5696 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5697 }
5698
Eric Laurentc4aef752013-09-12 17:45:53 -07005699 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5700 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5701 if (adev->visualizer_lib == NULL) {
5702 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5703 } else {
5704 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5705 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005706 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005707 "visualizer_hal_start_output");
5708 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005709 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005710 "visualizer_hal_stop_output");
5711 }
5712 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305713 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005714 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005715 audio_extn_gef_init(adev);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05305716 audio_extn_loopback_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005717
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005718 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5719 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5720 if (adev->offload_effects_lib == NULL) {
5721 ALOGE("%s: DLOPEN failed for %s", __func__,
5722 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5723 } else {
5724 ALOGV("%s: DLOPEN successful for %s", __func__,
5725 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5726 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305727 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005728 "offload_effects_bundle_hal_start_output");
5729 adev->offload_effects_stop_output =
5730 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5731 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005732 adev->offload_effects_set_hpx_state =
5733 (int (*)(bool))dlsym(adev->offload_effects_lib,
5734 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305735 adev->offload_effects_get_parameters =
5736 (void (*)(struct str_parms *, struct str_parms *))
5737 dlsym(adev->offload_effects_lib,
5738 "offload_effects_bundle_get_parameters");
5739 adev->offload_effects_set_parameters =
5740 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5741 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005742 }
5743 }
5744
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005745 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5746 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5747 if (adev->adm_lib == NULL) {
5748 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5749 } else {
5750 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5751 adev->adm_init = (adm_init_t)
5752 dlsym(adev->adm_lib, "adm_init");
5753 adev->adm_deinit = (adm_deinit_t)
5754 dlsym(adev->adm_lib, "adm_deinit");
5755 adev->adm_register_input_stream = (adm_register_input_stream_t)
5756 dlsym(adev->adm_lib, "adm_register_input_stream");
5757 adev->adm_register_output_stream = (adm_register_output_stream_t)
5758 dlsym(adev->adm_lib, "adm_register_output_stream");
5759 adev->adm_deregister_stream = (adm_deregister_stream_t)
5760 dlsym(adev->adm_lib, "adm_deregister_stream");
5761 adev->adm_request_focus = (adm_request_focus_t)
5762 dlsym(adev->adm_lib, "adm_request_focus");
5763 adev->adm_abandon_focus = (adm_abandon_focus_t)
5764 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005765 adev->adm_set_config = (adm_set_config_t)
5766 dlsym(adev->adm_lib, "adm_set_config");
5767 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5768 dlsym(adev->adm_lib, "adm_request_focus_v2");
5769 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5770 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5771 adev->adm_on_routing_change = (adm_on_routing_change_t)
5772 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005773 }
5774 }
5775
Mingming Yin514a8bc2014-07-29 15:22:21 -07005776 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005777 //initialize this to false for now,
5778 //this will be set to true through set param
5779 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005780
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005781 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005782 *device = &adev->device.common;
5783
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305784 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5785 &adev->streams_output_cfg_list,
5786 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005787
Kiran Kandi910e1862013-10-29 13:29:42 -07005788 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005789
5790 char value[PROPERTY_VALUE_MAX];
5791 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005792 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005793 trial = atoi(value);
5794 if (period_size_is_plausible_for_low_latency(trial)) {
5795 pcm_config_low_latency.period_size = trial;
5796 pcm_config_low_latency.start_threshold = trial / 4;
5797 pcm_config_low_latency.avail_min = trial / 4;
5798 configured_low_latency_capture_period_size = trial;
5799 }
5800 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005801 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005802 trial = atoi(value);
5803 if (period_size_is_plausible_for_low_latency(trial)) {
5804 configured_low_latency_capture_period_size = trial;
5805 }
5806 }
5807
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005808 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005809 af_period_multiplier = atoi(value);
5810 if (af_period_multiplier < 0)
5811 af_period_multiplier = 2;
5812 else if (af_period_multiplier > 4)
5813 af_period_multiplier = 4;
5814
5815 ALOGV("new period_multiplier = %d", af_period_multiplier);
5816 }
5817
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005818 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005819 pthread_mutex_unlock(&adev_init_lock);
5820
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005821 if (adev->adm_init)
5822 adev->adm_data = adev->adm_init();
5823
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305824 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305825 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005826 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305827
5828 audio_extn_snd_mon_init();
5829 pthread_mutex_lock(&adev->lock);
5830 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
5831 adev->card_status = CARD_STATUS_ONLINE;
5832 pthread_mutex_unlock(&adev->lock);
5833 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
5834
Eric Laurent994a6932013-07-17 11:51:42 -07005835 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005836 return 0;
5837}
5838
5839static struct hw_module_methods_t hal_module_methods = {
5840 .open = adev_open,
5841};
5842
5843struct audio_module HAL_MODULE_INFO_SYM = {
5844 .common = {
5845 .tag = HARDWARE_MODULE_TAG,
5846 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5847 .hal_api_version = HARDWARE_HAL_API_VERSION,
5848 .id = AUDIO_HARDWARE_MODULE_ID,
5849 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005850 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005851 .methods = &hal_module_methods,
5852 },
5853};