blob: 662032f00fad891163b4166e41e46fdf8d9f1e58 [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 Lataff613152017-07-18 18:19:21 -07003257 if ((AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) &&
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003258 !(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
Aniket Kumar Lataff613152017-07-18 18:19:21 -07003720 // Adjustment accounts for A2dp encoder latency with non offload usecases
3721 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3722 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3723 signed_frames -=
3724 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3725 }
3726
Eric Laurent949a0892013-09-20 09:20:13 -07003727 // It would be unusual for this value to be negative, but check just in case ...
3728 if (signed_frames >= 0) {
3729 *frames = signed_frames;
3730 ret = 0;
3731 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003732 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303733 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303734 *frames = out->written;
3735 clock_gettime(CLOCK_MONOTONIC, timestamp);
3736 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003737 }
3738 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003739 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003740 return ret;
3741}
3742
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003743static int out_set_callback(struct audio_stream_out *stream,
3744 stream_callback_t callback, void *cookie)
3745{
3746 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003747 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003748
3749 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003750 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003751 out->client_callback = callback;
3752 out->client_cookie = cookie;
3753 if (out->adsp_hdlr_stream_handle) {
3754 ret = audio_extn_adsp_hdlr_stream_set_callback(
3755 out->adsp_hdlr_stream_handle,
3756 callback,
3757 cookie);
3758 if (ret)
3759 ALOGW("%s:adsp hdlr callback registration failed %d",
3760 __func__, ret);
3761 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003762 pthread_mutex_unlock(&out->lock);
3763 return 0;
3764}
3765
3766static int out_pause(struct audio_stream_out* stream)
3767{
3768 struct stream_out *out = (struct stream_out *)stream;
3769 int status = -ENOSYS;
3770 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003771 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003772 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003773 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003774 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303775 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05303776 status = compress_pause(out->compr);
3777
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003778 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003779
Mingming Yin21854652016-04-13 11:54:02 -07003780 if (audio_extn_passthru_is_active()) {
3781 ALOGV("offload use case, pause passthru");
3782 audio_extn_passthru_on_pause(out);
3783 }
3784
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303785 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003786 audio_extn_dts_notify_playback_state(out->usecase, 0,
3787 out->sample_rate, popcount(out->channel_mask),
3788 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003789 }
3790 pthread_mutex_unlock(&out->lock);
3791 }
3792 return status;
3793}
3794
3795static int out_resume(struct audio_stream_out* stream)
3796{
3797 struct stream_out *out = (struct stream_out *)stream;
3798 int status = -ENOSYS;
3799 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003800 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003801 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003802 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003803 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003804 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303805 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303806 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003807 }
3808 if (!status) {
3809 out->offload_state = OFFLOAD_STATE_PLAYING;
3810 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303811 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003812 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3813 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003814 }
3815 pthread_mutex_unlock(&out->lock);
3816 }
3817 return status;
3818}
3819
3820static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3821{
3822 struct stream_out *out = (struct stream_out *)stream;
3823 int status = -ENOSYS;
3824 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003825 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003826 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003827 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3828 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3829 else
3830 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3831 pthread_mutex_unlock(&out->lock);
3832 }
3833 return status;
3834}
3835
3836static int out_flush(struct audio_stream_out* stream)
3837{
3838 struct stream_out *out = (struct stream_out *)stream;
3839 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003840 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003841 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003842 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003843 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3844 stop_compressed_output_l(out);
3845 out->written = 0;
3846 } else {
3847 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3848 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003849 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003850 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003851 return 0;
3852 }
3853 return -ENOSYS;
3854}
3855
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003856/** audio_stream_in implementation **/
3857static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3858{
3859 struct stream_in *in = (struct stream_in *)stream;
3860
3861 return in->config.rate;
3862}
3863
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003864static int in_set_sample_rate(struct audio_stream *stream __unused,
3865 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866{
3867 return -ENOSYS;
3868}
3869
3870static size_t in_get_buffer_size(const struct audio_stream *stream)
3871{
3872 struct stream_in *in = (struct stream_in *)stream;
3873
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003874 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3875 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003876 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
3877 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 -07003878 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3879 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303880 else if(audio_extn_cin_attached_usecase(in->usecase))
3881 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003882
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003883 return in->config.period_size * in->af_period_multiplier *
3884 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003885}
3886
3887static uint32_t in_get_channels(const struct audio_stream *stream)
3888{
3889 struct stream_in *in = (struct stream_in *)stream;
3890
3891 return in->channel_mask;
3892}
3893
3894static audio_format_t in_get_format(const struct audio_stream *stream)
3895{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003896 struct stream_in *in = (struct stream_in *)stream;
3897
3898 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899}
3900
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003901static int in_set_format(struct audio_stream *stream __unused,
3902 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903{
3904 return -ENOSYS;
3905}
3906
3907static int in_standby(struct audio_stream *stream)
3908{
3909 struct stream_in *in = (struct stream_in *)stream;
3910 struct audio_device *adev = in->dev;
3911 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303912 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3913 stream, in->usecase, use_case_table[in->usecase]);
3914
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003915 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003916 if (!in->standby && in->is_st_session) {
3917 ALOGD("%s: sound trigger pcm stop lab", __func__);
3918 audio_extn_sound_trigger_stop_lab(in);
3919 in->standby = 1;
3920 }
3921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003922 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003923 if (adev->adm_deregister_stream)
3924 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3925
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003926 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003927 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003928 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3929 voice_extn_compress_voip_close_input_stream(stream);
3930 ALOGD("VOIP input entered standby");
3931 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303932 if (audio_extn_cin_attached_usecase(in->usecase))
3933 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003934 if (in->pcm) {
3935 pcm_close(in->pcm);
3936 in->pcm = NULL;
3937 }
3938 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003939 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003940 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003941 }
3942 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003943 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003944 return status;
3945}
3946
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003947static int in_dump(const struct audio_stream *stream __unused,
3948 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003949{
3950 return 0;
3951}
3952
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303953static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3954{
3955 if (!stream || !parms)
3956 return;
3957
3958 struct stream_in *in = (struct stream_in *)stream;
3959 struct audio_device *adev = in->dev;
3960
3961 card_status_t status;
3962 int card;
3963 if (parse_snd_card_status(parms, &card, &status) < 0)
3964 return;
3965
3966 pthread_mutex_lock(&adev->lock);
3967 bool valid_cb = (card == adev->snd_card);
3968 pthread_mutex_unlock(&adev->lock);
3969
3970 if (!valid_cb)
3971 return;
3972
3973 lock_input_stream(in);
3974 if (in->card_status != status)
3975 in->card_status = status;
3976 pthread_mutex_unlock(&in->lock);
3977
3978 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3979 use_case_table[in->usecase],
3980 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3981
3982 // a better solution would be to report error back to AF and let
3983 // it put the stream to standby
3984 if (status == CARD_STATUS_OFFLINE)
3985 in_standby(&in->stream.common);
3986
3987 return;
3988}
3989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003990static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3991{
3992 struct stream_in *in = (struct stream_in *)stream;
3993 struct audio_device *adev = in->dev;
3994 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003995 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003996 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003997
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303998 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003999 parms = str_parms_create_str(kvpairs);
4000
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304001 if (!parms)
4002 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004003 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004004 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004005
4006 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4007 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004008 val = atoi(value);
4009 /* no audio source uses val == 0 */
4010 if ((in->source != val) && (val != 0)) {
4011 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004012 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4013 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4014 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004015 (in->config.rate == 8000 || in->config.rate == 16000 ||
4016 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004017 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004018 err = voice_extn_compress_voip_open_input_stream(in);
4019 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004020 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004021 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004022 }
4023 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024 }
4025 }
4026
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004027 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4028 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004029 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004030 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004031 in->device = val;
4032 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004033 if (!in->standby && !in->is_st_session) {
4034 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07004035 if (adev->adm_on_routing_change)
4036 adev->adm_on_routing_change(adev->adm_data,
4037 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004038 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004039 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004040 }
4041 }
4042
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304043 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4044 if (err >= 0) {
4045 strlcpy(in->profile, value, sizeof(in->profile));
4046 ALOGV("updating stream profile with value '%s'", in->profile);
4047 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4048 &adev->streams_input_cfg_list,
4049 in->device, in->flags, in->format,
4050 in->sample_rate, in->bit_width,
4051 in->profile, &in->app_type_cfg);
4052 }
4053
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004054 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004055 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004056
4057 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304058error:
Eric Laurent994a6932013-07-17 11:51:42 -07004059 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060 return ret;
4061}
4062
4063static char* in_get_parameters(const struct audio_stream *stream,
4064 const char *keys)
4065{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004066 struct stream_in *in = (struct stream_in *)stream;
4067 struct str_parms *query = str_parms_create_str(keys);
4068 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004069 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004070
4071 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004072 if (reply) {
4073 str_parms_destroy(reply);
4074 }
4075 if (query) {
4076 str_parms_destroy(query);
4077 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004078 ALOGE("in_get_parameters: failed to create query or reply");
4079 return NULL;
4080 }
4081
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004082 ALOGV("%s: enter: keys - %s", __func__, keys);
4083
4084 voice_extn_in_get_parameters(in, query, reply);
4085
4086 str = str_parms_to_str(reply);
4087 str_parms_destroy(query);
4088 str_parms_destroy(reply);
4089
4090 ALOGV("%s: exit: returns - %s", __func__, str);
4091 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004092}
4093
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004094static int in_set_gain(struct audio_stream_in *stream __unused,
4095 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004096{
4097 return 0;
4098}
4099
4100static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4101 size_t bytes)
4102{
4103 struct stream_in *in = (struct stream_in *)stream;
4104 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304105 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304106 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004107
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004108 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304109
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004110 if (in->is_st_session) {
4111 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
4112 /* Read from sound trigger HAL */
4113 audio_extn_sound_trigger_read(in, buffer, bytes);
4114 pthread_mutex_unlock(&in->lock);
4115 return bytes;
4116 }
4117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004118 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004119 pthread_mutex_lock(&adev->lock);
4120 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
4121 ret = voice_extn_compress_voip_start_input_stream(in);
4122 else
4123 ret = start_input_stream(in);
4124 pthread_mutex_unlock(&adev->lock);
4125 if (ret != 0) {
4126 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004127 }
4128 in->standby = 0;
4129 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004131 // what's the duration requested by the client?
4132 long ns = 0;
4133
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304134 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004135 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4136 in->config.rate;
4137
4138 request_in_focus(in, ns);
4139 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004140
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304141 if (audio_extn_cin_attached_usecase(in->usecase)) {
4142 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
4143 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304144 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004145 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304146 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07004147 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004148 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004149 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304150 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004151 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304152 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4153 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4154 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
4155 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304156 ret = -EINVAL;
4157 goto exit;
4158 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304159 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304160 ret = -errno;
4161 }
4162 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304163 /* bytes read is always set to bytes for non compress usecases */
4164 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004165 }
4166
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004167 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004168
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004169 /*
4170 * Instead of writing zeroes here, we could trust the hardware
4171 * to always provide zeroes when muted.
4172 */
Pavan Chikkala63964842014-12-04 10:48:28 +05304173 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
4174 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004175 memset(buffer, 0, bytes);
4176
4177exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004178 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304179 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004180 pthread_mutex_unlock(&in->lock);
4181
4182 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304183 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304184 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304185 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304186 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304187 in->standby = true;
4188 }
Sharad Sangled17c9122017-03-20 15:58:52 +05304189 if (!audio_extn_cin_attached_usecase(in->usecase)) {
4190 bytes_read = bytes;
4191 memset(buffer, 0, bytes);
4192 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004193 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004194 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05304195 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05304196 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004197 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304198 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004199}
4200
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004201static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004202{
4203 return 0;
4204}
4205
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004206static int add_remove_audio_effect(const struct audio_stream *stream,
4207 effect_handle_t effect,
4208 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004209{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004210 struct stream_in *in = (struct stream_in *)stream;
4211 int status = 0;
4212 effect_descriptor_t desc;
4213
4214 status = (*effect)->get_descriptor(effect, &desc);
4215 if (status != 0)
4216 return status;
4217
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004218 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004219 pthread_mutex_lock(&in->dev->lock);
4220 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4221 in->enable_aec != enable &&
4222 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4223 in->enable_aec = enable;
4224 if (!in->standby)
4225 select_devices(in->dev, in->usecase);
4226 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08004227 if (in->enable_ns != enable &&
4228 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4229 in->enable_ns = enable;
4230 if (!in->standby)
4231 select_devices(in->dev, in->usecase);
4232 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004233 pthread_mutex_unlock(&in->dev->lock);
4234 pthread_mutex_unlock(&in->lock);
4235
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004236 return 0;
4237}
4238
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004239static int in_add_audio_effect(const struct audio_stream *stream,
4240 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004241{
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, true);
4244}
4245
4246static int in_remove_audio_effect(const struct audio_stream *stream,
4247 effect_handle_t effect)
4248{
Eric Laurent994a6932013-07-17 11:51:42 -07004249 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004250 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004251}
4252
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304253int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004254 audio_io_handle_t handle,
4255 audio_devices_t devices,
4256 audio_output_flags_t flags,
4257 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004258 struct audio_stream_out **stream_out,
4259 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004260{
4261 struct audio_device *adev = (struct audio_device *)dev;
4262 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304263 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004264 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004265 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004266
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004267 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304268
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004269 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4270
Mingming Yin3a941d42016-02-17 18:08:05 -08004271 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
4272 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304273 devices, flags, &out->stream);
4274
4275
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004276 if (!out) {
4277 return -ENOMEM;
4278 }
4279
Haynes Mathew George204045b2015-02-25 20:32:03 -08004280 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004281 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08004282 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004284 if (devices == AUDIO_DEVICE_NONE)
4285 devices = AUDIO_DEVICE_OUT_SPEAKER;
4286
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004287 out->flags = flags;
4288 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004289 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004290 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004291 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05304292 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004293 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07004294 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004295 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08004296 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304297 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304298 out->started = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004299
Mingming Yin3a941d42016-02-17 18:08:05 -08004300 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4301 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
4302 pthread_mutex_lock(&adev->lock);
4303 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
4304 ret = read_hdmi_sink_caps(out);
4305 pthread_mutex_unlock(&adev->lock);
4306 if (ret != 0) {
4307 if (ret == -ENOSYS) {
4308 /* ignore and go with default */
4309 ret = 0;
4310 } else {
4311 ALOGE("error reading hdmi sink caps");
4312 goto error_open;
4313 }
4314 }
4315 }
4316
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004317 /* Init use case and pcm_config */
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004318#ifndef COMPRESS_VOIP_ENABLED
4319 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4320 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
4321 out->sample_rate == 32000 || out->sample_rate == 48000)) {
4322 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
4323 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
4324 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4325
4326 out->config = default_pcm_config_voip_copp;
4327 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
4328 out->config.rate = out->sample_rate;
4329
4330#else
Dhananjay Kumarac341582017-02-23 23:42:25 +05304331 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004332 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08004333 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004334 ret = voice_extn_compress_voip_open_output_stream(out);
4335 if (ret != 0) {
4336 ALOGE("%s: Compress voip output cannot be opened, error:%d",
4337 __func__, ret);
4338 goto error_open;
4339 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004340#endif
vivek mehta0ea887a2015-08-26 14:01:20 -07004341 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304342 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304343 pthread_mutex_lock(&adev->lock);
4344 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4345 pthread_mutex_unlock(&adev->lock);
4346
4347 // reject offload during card offline to allow
4348 // fallback to s/w paths
4349 if (offline) {
4350 ret = -ENODEV;
4351 goto error_open;
4352 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004353
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004354 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4355 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4356 ALOGE("%s: Unsupported Offload information", __func__);
4357 ret = -EINVAL;
4358 goto error_open;
4359 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004360
Mingming Yin3a941d42016-02-17 18:08:05 -08004361 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004362 if(config->offload_info.format == 0)
4363 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004364 if (config->offload_info.sample_rate == 0)
4365 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004366 }
4367
Mingming Yin90310102013-11-13 16:57:00 -08004368 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304369 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004370 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004371 ret = -EINVAL;
4372 goto error_open;
4373 }
4374
Ben Romberger0f8c87b2017-05-24 17:41:11 -07004375 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
4376 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
4377 (audio_extn_passthru_is_passthrough_stream(out)) &&
4378 !((config->sample_rate == 48000) ||
4379 (config->sample_rate == 96000) ||
4380 (config->sample_rate == 192000))) {
4381 ALOGE("%s: Unsupported sample rate %d for audio format %x",
4382 __func__, config->sample_rate, config->offload_info.format);
4383 ret = -EINVAL;
4384 goto error_open;
4385 }
4386
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004387 out->compr_config.codec = (struct snd_codec *)
4388 calloc(1, sizeof(struct snd_codec));
4389
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004390 if (!out->compr_config.codec) {
4391 ret = -ENOMEM;
4392 goto error_open;
4393 }
4394
Dhananjay Kumarac341582017-02-23 23:42:25 +05304395 out->stream.pause = out_pause;
4396 out->stream.resume = out_resume;
4397 out->stream.flush = out_flush;
4398 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004399 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004400 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304401 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004402 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304403 } else {
4404 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4405 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004406 }
vivek mehta446c3962015-09-14 10:57:35 -07004407
4408 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004409 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4410 config->format == 0 && config->sample_rate == 0 &&
4411 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004412 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004413 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4414 } else {
4415 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4416 ret = -EEXIST;
4417 goto error_open;
4418 }
vivek mehta446c3962015-09-14 10:57:35 -07004419 }
4420
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004421 if (config->offload_info.channel_mask)
4422 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004423 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004424 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004425 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004426 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304427 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004428 ret = -EINVAL;
4429 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004430 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004431
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004432 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004433 out->sample_rate = config->offload_info.sample_rate;
4434
Mingming Yin3ee55c62014-08-04 14:23:35 -07004435 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004436
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304437 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4438 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4439 audio_extn_dolby_send_ddp_endp_params(adev);
4440 audio_extn_dolby_set_dmid(adev);
4441 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004442
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004443 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004444 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004445 out->compr_config.codec->bit_rate =
4446 config->offload_info.bit_rate;
4447 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304448 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004449 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304450 /* Update bit width only for non passthrough usecases.
4451 * For passthrough usecases, the output will always be opened @16 bit
4452 */
4453 if (!audio_extn_passthru_is_passthrough_stream(out))
4454 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304455
4456 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4457 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
4458 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
4459
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004460 /*TODO: Do we need to change it for passthrough */
4461 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004462
Manish Dewangana6fc5442015-08-24 20:30:31 +05304463 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4464 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304465 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304466 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304467 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4468 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304469
4470 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4471 AUDIO_FORMAT_PCM) {
4472
4473 /*Based on platform support, configure appropriate alsa format for corresponding
4474 *hal input format.
4475 */
4476 out->compr_config.codec->format = hal_format_to_alsa(
4477 config->offload_info.format);
4478
Ashish Jain83a6cc22016-06-28 14:34:17 +05304479 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304480 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304481 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304482
Dhananjay Kumarac341582017-02-23 23:42:25 +05304483 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304484 *hal input format and alsa format might differ based on platform support.
4485 */
4486 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304487 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304488
4489 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4490
4491 /* Check if alsa session is configured with the same format as HAL input format,
4492 * if not then derive correct fragment size needed to accomodate the
4493 * conversion of HAL input format to alsa format.
4494 */
4495 audio_extn_utils_update_direct_pcm_fragment_size(out);
4496
4497 /*if hal input and output fragment size is different this indicates HAL input format is
4498 *not same as the alsa format
4499 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304500 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304501 /*Allocate a buffer to convert input data to the alsa configured format.
4502 *size of convert buffer is equal to the size required to hold one fragment size
4503 *worth of pcm data, this is because flinger does not write more than fragment_size
4504 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304505 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4506 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304507 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4508 ret = -ENOMEM;
4509 goto error_open;
4510 }
4511 }
4512 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4513 out->compr_config.fragment_size =
4514 audio_extn_passthru_get_buffer_size(&config->offload_info);
4515 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4516 } else {
4517 out->compr_config.fragment_size =
4518 platform_get_compress_offload_buffer_size(&config->offload_info);
4519 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4520 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004521
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304522 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4523 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
4524 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07004525 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304526 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004527
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304528 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4529 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4530 }
4531
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004532 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4533 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004534
Manish Dewangan69426c82017-01-30 17:35:36 +05304535 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
4536 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
4537 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
4538 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4539 out->render_mode = RENDER_MODE_AUDIO_MASTER;
4540 } else {
4541 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
4542 }
Alexy Josephaa54c872014-12-03 02:46:47 -08004543
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05304544 memset(&out->channel_map_param, 0,
4545 sizeof(struct audio_out_channel_map_param));
4546
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004547 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304548 out->send_next_track_params = false;
4549 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004550 out->offload_state = OFFLOAD_STATE_IDLE;
4551 out->playback_started = 0;
4552
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004553 audio_extn_dts_create_state_notifier_node(out->usecase);
4554
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004555 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4556 __func__, config->offload_info.version,
4557 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304558
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304559 /* Check if DSD audio format is supported in codec
4560 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304561 */
4562
4563 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304564 (!platform_check_codec_dsd_support(adev->platform) ||
4565 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304566 ret = -EINVAL;
4567 goto error_open;
4568 }
4569
Ashish Jain5106d362016-05-11 19:23:33 +05304570 /* Disable gapless if any of the following is true
4571 * passthrough playback
4572 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304573 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304574 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304575 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304576 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07004577 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304578 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304579 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304580 check_and_set_gapless_mode(adev, false);
4581 } else
4582 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004583
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304584 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004585 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4586 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304587 if (config->format == AUDIO_FORMAT_DSD) {
4588 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4589 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4590 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004591
4592 create_offload_callback_thread(out);
4593
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004594 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304595 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004596 if (ret != 0) {
4597 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4598 __func__, ret);
4599 goto error_open;
4600 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004601 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4602 if (config->sample_rate == 0)
4603 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4604 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4605 config->sample_rate != 8000) {
4606 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4607 ret = -EINVAL;
4608 goto error_open;
4609 }
4610 out->sample_rate = config->sample_rate;
4611 out->config.rate = config->sample_rate;
4612 if (config->format == AUDIO_FORMAT_DEFAULT)
4613 config->format = AUDIO_FORMAT_PCM_16_BIT;
4614 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4615 config->format = AUDIO_FORMAT_PCM_16_BIT;
4616 ret = -EINVAL;
4617 goto error_open;
4618 }
4619 out->format = config->format;
4620 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4621 out->config = pcm_config_afe_proxy_playback;
4622 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004623 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304624 unsigned int channels = 0;
4625 /*Update config params to default if not set by the caller*/
4626 if (config->sample_rate == 0)
4627 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4628 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4629 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4630 if (config->format == AUDIO_FORMAT_DEFAULT)
4631 config->format = AUDIO_FORMAT_PCM_16_BIT;
4632
4633 channels = audio_channel_count_from_out_mask(out->channel_mask);
4634
Ashish Jain83a6cc22016-06-28 14:34:17 +05304635 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4636 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004637 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4638 out->flags);
4639 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304640 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4641 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4642 out->config = pcm_config_low_latency;
4643 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4644 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4645 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304646 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4647 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4648 if (out->config.period_size <= 0) {
4649 ALOGE("Invalid configuration period size is not valid");
4650 ret = -EINVAL;
4651 goto error_open;
4652 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304653 } else {
4654 /* primary path is the default path selected if no other outputs are available/suitable */
4655 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4656 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4657 }
4658 out->hal_ip_format = format = out->format;
4659 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4660 out->hal_op_format = pcm_format_to_hal(out->config.format);
4661 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4662 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004663 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304664 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304665 if (out->hal_ip_format != out->hal_op_format) {
4666 uint32_t buffer_size = out->config.period_size *
4667 format_to_bitwidth_table[out->hal_op_format] *
4668 out->config.channels;
4669 out->convert_buffer = calloc(1, buffer_size);
4670 if (out->convert_buffer == NULL){
4671 ALOGE("Allocation failed for convert buffer for size %d",
4672 out->compr_config.fragment_size);
4673 ret = -ENOMEM;
4674 goto error_open;
4675 }
4676 ALOGD("Convert buffer allocated of size %d", buffer_size);
4677 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004678 }
4679
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004680 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4681 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304682
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004683 /* TODO remove this hardcoding and check why width is zero*/
4684 if (out->bit_width == 0)
4685 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304686 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004687 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304688 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304689 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304690 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004691 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4692 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4693 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004694 if(adev->primary_output == NULL)
4695 adev->primary_output = out;
4696 else {
4697 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004698 ret = -EEXIST;
4699 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004700 }
4701 }
4702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004703 /* Check if this usecase is already existing */
4704 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004705 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4706 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004708 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004709 ret = -EEXIST;
4710 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004711 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004712
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004713 pthread_mutex_unlock(&adev->lock);
4714
4715 out->stream.common.get_sample_rate = out_get_sample_rate;
4716 out->stream.common.set_sample_rate = out_set_sample_rate;
4717 out->stream.common.get_buffer_size = out_get_buffer_size;
4718 out->stream.common.get_channels = out_get_channels;
4719 out->stream.common.get_format = out_get_format;
4720 out->stream.common.set_format = out_set_format;
4721 out->stream.common.standby = out_standby;
4722 out->stream.common.dump = out_dump;
4723 out->stream.common.set_parameters = out_set_parameters;
4724 out->stream.common.get_parameters = out_get_parameters;
4725 out->stream.common.add_audio_effect = out_add_audio_effect;
4726 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4727 out->stream.get_latency = out_get_latency;
4728 out->stream.set_volume = out_set_volume;
4729 out->stream.write = out_write;
4730 out->stream.get_render_position = out_get_render_position;
4731 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004732 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004733
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004734 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004735 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004736 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004737 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004738
4739 config->format = out->stream.common.get_format(&out->stream.common);
4740 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4741 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4742
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304743 /*
4744 By locking output stream before registering, we allow the callback
4745 to update stream's state only after stream's initial state is set to
4746 adev state.
4747 */
4748 lock_output_stream(out);
4749 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4750 pthread_mutex_lock(&adev->lock);
4751 out->card_status = adev->card_status;
4752 pthread_mutex_unlock(&adev->lock);
4753 pthread_mutex_unlock(&out->lock);
4754
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004755 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304756 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004757 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004758
4759 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4760 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4761 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004762 /* setup a channel for client <--> adsp communication for stream events */
4763 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07004764 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
4765 (audio_extn_ip_hdlr_intf_supported(config->format))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004766 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
4767 out->usecase, PCM_PLAYBACK);
4768 hdlr_stream_cfg.flags = out->flags;
4769 hdlr_stream_cfg.type = PCM_PLAYBACK;
4770 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
4771 &hdlr_stream_cfg);
4772 if (ret) {
4773 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
4774 out->adsp_hdlr_stream_handle = NULL;
4775 }
4776 }
Naresh Tanniru85819452017-05-04 18:55:45 -07004777 if (audio_extn_ip_hdlr_intf_supported(config->format)) {
4778 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL);
4779 if (ret < 0) {
4780 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
4781 out->ip_hdlr_handle = NULL;
4782 }
4783 }
Eric Laurent994a6932013-07-17 11:51:42 -07004784 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004785 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004786
4787error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304788 if (out->convert_buffer)
4789 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004790 free(out);
4791 *stream_out = NULL;
4792 ALOGD("%s: exit: ret %d", __func__, ret);
4793 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004794}
4795
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304796void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004797 struct audio_stream_out *stream)
4798{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004799 struct stream_out *out = (struct stream_out *)stream;
4800 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004801 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004802
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304803 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4804
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304805 // must deregister from sndmonitor first to prevent races
4806 // between the callback and close_stream
4807 audio_extn_snd_mon_unregister_listener(out);
4808
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004809 /* close adsp hdrl session before standby */
4810 if (out->adsp_hdlr_stream_handle) {
4811 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
4812 if (ret)
4813 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
4814 out->adsp_hdlr_stream_handle = NULL;
4815 }
4816
Naresh Tanniru85819452017-05-04 18:55:45 -07004817 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
4818 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
4819 out->ip_hdlr_handle = NULL;
4820 }
4821
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004822 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304823 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004824 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304825 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304826 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004827 if(ret != 0)
4828 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4829 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004830 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004831 out_standby(&stream->common);
4832
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004833 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004834 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004835 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004836 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004837 if (out->compr_config.codec != NULL)
4838 free(out->compr_config.codec);
4839 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004840
Ashish Jain83a6cc22016-06-28 14:34:17 +05304841 if (out->convert_buffer != NULL) {
4842 free(out->convert_buffer);
4843 out->convert_buffer = NULL;
4844 }
4845
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004846 if (adev->voice_tx_output == out)
4847 adev->voice_tx_output = NULL;
4848
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304849 if (adev->primary_output == out)
4850 adev->primary_output = NULL;
4851
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004852 pthread_cond_destroy(&out->cond);
4853 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004854 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004855 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004856}
4857
4858static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4859{
4860 struct audio_device *adev = (struct audio_device *)dev;
4861 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004862 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004863 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004864 int ret;
4865 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004866
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004867 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004868 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004869
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304870 if (!parms)
4871 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304872
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304873 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
4874 if (ret >= 0) {
4875 /* When set to false, HAL should disable EC and NS */
4876 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4877 adev->bt_sco_on = true;
4878 else
4879 adev->bt_sco_on = false;
4880 }
4881
Naresh Tanniru4c630392014-05-12 01:05:52 +05304882 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004883 status = voice_set_parameters(adev, parms);
4884 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004885 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004886
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004887 status = platform_set_parameters(adev->platform, parms);
4888 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004889 goto done;
4890
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004891 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4892 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004893 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004894 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4895 adev->bluetooth_nrec = true;
4896 else
4897 adev->bluetooth_nrec = false;
4898 }
4899
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004900 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4901 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004902 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4903 adev->screen_off = false;
4904 else
4905 adev->screen_off = true;
4906 }
4907
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004908 ret = str_parms_get_int(parms, "rotation", &val);
4909 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004910 bool reverse_speakers = false;
4911 switch(val) {
4912 // FIXME: note that the code below assumes that the speakers are in the correct placement
4913 // relative to the user when the device is rotated 90deg from its default rotation. This
4914 // assumption is device-specific, not platform-specific like this code.
4915 case 270:
4916 reverse_speakers = true;
4917 break;
4918 case 0:
4919 case 90:
4920 case 180:
4921 break;
4922 default:
4923 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004924 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004925 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004926 if (status == 0) {
4927 if (adev->speaker_lr_swap != reverse_speakers) {
4928 adev->speaker_lr_swap = reverse_speakers;
4929 // only update the selected device if there is active pcm playback
4930 struct audio_usecase *usecase;
4931 struct listnode *node;
4932 list_for_each(node, &adev->usecase_list) {
4933 usecase = node_to_item(node, struct audio_usecase, list);
4934 if (usecase->type == PCM_PLAYBACK) {
4935 select_devices(adev, usecase->id);
4936 break;
4937 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004938 }
4939 }
4940 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004941 }
4942
Mingming Yin514a8bc2014-07-29 15:22:21 -07004943 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4944 if (ret >= 0) {
4945 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4946 adev->bt_wb_speech_enabled = true;
4947 else
4948 adev->bt_wb_speech_enabled = false;
4949 }
4950
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004951 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4952 if (ret >= 0) {
4953 val = atoi(value);
4954 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004955 ALOGV("cache new ext disp type and edid");
4956 ret = platform_get_ext_disp_type(adev->platform);
4957 if (ret < 0) {
4958 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004959 status = ret;
4960 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004961 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004962 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004963 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004964 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004965 /*
4966 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4967 * Per AudioPolicyManager, USB device is higher priority than WFD.
4968 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4969 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4970 * starting voice call on USB
4971 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004972 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4973 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004974 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4975 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004976 }
vivek mehta344576a2016-04-12 18:56:03 -07004977 ALOGV("detected USB connect .. disable proxy");
4978 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004979 }
4980 }
4981
4982 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4983 if (ret >= 0) {
4984 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004985 /*
4986 * The HDMI / Displayport disconnect handling has been moved to
4987 * audio extension to ensure that its parameters are not
4988 * invalidated prior to updating sysfs of the disconnect event
4989 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4990 */
4991 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004992 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004993 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4994 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304995 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4996 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004997 }
vivek mehta344576a2016-04-12 18:56:03 -07004998 ALOGV("detected USB disconnect .. enable proxy");
4999 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005000 }
5001 }
5002
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305003 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
5004 if (ret >= 0) {
5005 struct audio_usecase *usecase;
5006 struct listnode *node;
5007 list_for_each(node, &adev->usecase_list) {
5008 usecase = node_to_item(node, struct audio_usecase, list);
5009 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07005010 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305011 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08005012
5013 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305014 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08005015 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305016 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305017 //force device switch to re configure encoder
5018 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305019 audio_extn_a2dp_set_handoff_mode(false);
5020 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305021 break;
5022 }
5023 }
5024 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005025
5026 //handle vr audio setparam
5027 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5028 value, sizeof(value));
5029 if (ret >= 0) {
5030 ALOGI("Setting vr mode to be %s", value);
5031 if (!strncmp(value, "true", 4)) {
5032 adev->vr_audio_mode_enabled = true;
5033 ALOGI("Setting vr mode to true");
5034 } else if (!strncmp(value, "false", 5)) {
5035 adev->vr_audio_mode_enabled = false;
5036 ALOGI("Setting vr mode to false");
5037 } else {
5038 ALOGI("wrong vr mode set");
5039 }
5040 }
5041
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305042 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005043done:
5044 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005045 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305046error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005047 ALOGV("%s: exit with code(%d)", __func__, status);
5048 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005049}
5050
5051static char* adev_get_parameters(const struct audio_hw_device *dev,
5052 const char *keys)
5053{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005054 struct audio_device *adev = (struct audio_device *)dev;
5055 struct str_parms *reply = str_parms_create();
5056 struct str_parms *query = str_parms_create_str(keys);
5057 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05305058 char value[256] = {0};
5059 int ret = 0;
5060
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005061 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005062 if (reply) {
5063 str_parms_destroy(reply);
5064 }
5065 if (query) {
5066 str_parms_destroy(query);
5067 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005068 ALOGE("adev_get_parameters: failed to create query or reply");
5069 return NULL;
5070 }
5071
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005072 //handle vr audio getparam
5073
5074 ret = str_parms_get_str(query,
5075 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5076 value, sizeof(value));
5077
5078 if (ret >= 0) {
5079 bool vr_audio_enabled = false;
5080 pthread_mutex_lock(&adev->lock);
5081 vr_audio_enabled = adev->vr_audio_mode_enabled;
5082 pthread_mutex_unlock(&adev->lock);
5083
5084 ALOGI("getting vr mode to %d", vr_audio_enabled);
5085
5086 if (vr_audio_enabled) {
5087 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5088 "true");
5089 goto exit;
5090 } else {
5091 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5092 "false");
5093 goto exit;
5094 }
5095 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005096
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005097 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005098 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08005099 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005100 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05305101 pthread_mutex_unlock(&adev->lock);
5102
Naresh Tannirud7205b62014-06-20 02:54:48 +05305103exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005104 str = str_parms_to_str(reply);
5105 str_parms_destroy(query);
5106 str_parms_destroy(reply);
5107
5108 ALOGV("%s: exit: returns - %s", __func__, str);
5109 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005110}
5111
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005112static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005113{
5114 return 0;
5115}
5116
5117static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5118{
Haynes Mathew George5191a852013-09-11 14:19:36 -07005119 int ret;
5120 struct audio_device *adev = (struct audio_device *)dev;
5121 pthread_mutex_lock(&adev->lock);
5122 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07005123 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005124 pthread_mutex_unlock(&adev->lock);
5125 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005126}
5127
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005128static int adev_set_master_volume(struct audio_hw_device *dev __unused,
5129 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005130{
5131 return -ENOSYS;
5132}
5133
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005134static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5135 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005136{
5137 return -ENOSYS;
5138}
5139
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005140static int adev_set_master_mute(struct audio_hw_device *dev __unused,
5141 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005142{
5143 return -ENOSYS;
5144}
5145
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005146static int adev_get_master_mute(struct audio_hw_device *dev __unused,
5147 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005148{
5149 return -ENOSYS;
5150}
5151
5152static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5153{
5154 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005155
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005156 pthread_mutex_lock(&adev->lock);
5157 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005158 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005159 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08005160 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005161 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07005162 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005163 adev->current_call_output = NULL;
5164 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005165 }
5166 pthread_mutex_unlock(&adev->lock);
5167 return 0;
5168}
5169
5170static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5171{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005172 int ret;
5173
5174 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08005175 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005176 ret = voice_set_mic_mute((struct audio_device *)dev, state);
5177 pthread_mutex_unlock(&adev->lock);
5178
5179 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005180}
5181
5182static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5183{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005184 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005185 return 0;
5186}
5187
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005188static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005189 const struct audio_config *config)
5190{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005191 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005192
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005193 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
5194 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005195}
5196
5197static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005198 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005199 audio_devices_t devices,
5200 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005201 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305202 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005203 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005204 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005205{
5206 struct audio_device *adev = (struct audio_device *)dev;
5207 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005208 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005209 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005210 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305211 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305212
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005213 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305214 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
5215 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005216 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305217 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005218
5219 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005220
5221 if (!in) {
5222 ALOGE("failed to allocate input stream");
5223 return -ENOMEM;
5224 }
5225
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305226 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305227 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
5228 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005229 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005230 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005231
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005232 in->stream.common.get_sample_rate = in_get_sample_rate;
5233 in->stream.common.set_sample_rate = in_set_sample_rate;
5234 in->stream.common.get_buffer_size = in_get_buffer_size;
5235 in->stream.common.get_channels = in_get_channels;
5236 in->stream.common.get_format = in_get_format;
5237 in->stream.common.set_format = in_set_format;
5238 in->stream.common.standby = in_standby;
5239 in->stream.common.dump = in_dump;
5240 in->stream.common.set_parameters = in_set_parameters;
5241 in->stream.common.get_parameters = in_get_parameters;
5242 in->stream.common.add_audio_effect = in_add_audio_effect;
5243 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5244 in->stream.set_gain = in_set_gain;
5245 in->stream.read = in_read;
5246 in->stream.get_input_frames_lost = in_get_input_frames_lost;
5247
5248 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005249 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005250 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005251 in->standby = 1;
5252 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005253 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005254 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005255
Dhananjay Kumar973fc362017-01-09 18:48:15 +05305256 in->usecase = USECASE_AUDIO_RECORD;
5257 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
5258 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
5259 is_low_latency = true;
5260#if LOW_LATENCY_CAPTURE_USE_CASE
5261 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
5262#endif
5263 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
5264 }
5265
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005266 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005267 if (in->realtime) {
5268 in->config = pcm_config_audio_capture_rt;
5269 in->sample_rate = in->config.rate;
5270 in->af_period_multiplier = af_period_multiplier;
5271 } else {
5272 in->config = pcm_config_audio_capture;
5273 in->config.rate = config->sample_rate;
5274 in->sample_rate = config->sample_rate;
5275 in->af_period_multiplier = 1;
5276 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305277 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005278
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305279 /* restrict 24 bit capture for unprocessed source only
5280 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
5281 */
5282 if (config->format == AUDIO_FORMAT_DEFAULT) {
5283 config->format = AUDIO_FORMAT_PCM_16_BIT;
5284 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
5285 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
5286 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
5287 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5288 bool ret_error = false;
5289 in->bit_width = 24;
5290 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5291 from HAL is 24_packed and 8_24
5292 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5293 24_packed return error indicating supported format is 24_packed
5294 *> In case of any other source requesting 24 bit or float return error
5295 indicating format supported is 16 bit only.
5296
5297 on error flinger will retry with supported format passed
5298 */
5299 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
5300 (source != AUDIO_SOURCE_CAMCORDER)) {
5301 config->format = AUDIO_FORMAT_PCM_16_BIT;
5302 if (config->sample_rate > 48000)
5303 config->sample_rate = 48000;
5304 ret_error = true;
5305 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
5306 in->config.format = PCM_FORMAT_S24_3LE;
5307 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5308 in->config.format = PCM_FORMAT_S24_LE;
5309 } else {
5310 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
5311 ret_error = true;
5312 }
5313
5314 if (ret_error) {
5315 ret = -EINVAL;
5316 goto err_open;
5317 }
5318 }
5319
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305320 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305321 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
5322 (adev->mode != AUDIO_MODE_IN_CALL)) {
5323 ret = -EINVAL;
5324 goto err_open;
5325 }
5326
5327 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
5328 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005329 if (config->sample_rate == 0)
5330 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5331 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5332 config->sample_rate != 8000) {
5333 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5334 ret = -EINVAL;
5335 goto err_open;
5336 }
5337 if (config->format == AUDIO_FORMAT_DEFAULT)
5338 config->format = AUDIO_FORMAT_PCM_16_BIT;
5339 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5340 config->format = AUDIO_FORMAT_PCM_16_BIT;
5341 ret = -EINVAL;
5342 goto err_open;
5343 }
5344
5345 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5346 in->config = pcm_config_afe_proxy_record;
5347 in->config.channels = channel_count;
5348 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305349 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305350 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
5351 in, config, &channel_mask_updated)) {
5352 if (channel_mask_updated == true) {
5353 ALOGD("%s: return error to retry with updated channel mask (%#x)",
5354 __func__, config->channel_mask);
5355 ret = -EINVAL;
5356 goto err_open;
5357 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05305358 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07005359 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005360 audio_extn_compr_cap_format_supported(config->format) &&
5361 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005362 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305363 } else if (audio_extn_cin_applicable_stream(in)) {
5364 ret = audio_extn_cin_configure_input_stream(in);
5365 if (ret)
5366 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005367 } else {
5368 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005369 if (!in->realtime) {
5370 in->format = config->format;
5371 frame_size = audio_stream_in_frame_size(&in->stream);
5372 buffer_size = get_input_buffer_size(config->sample_rate,
5373 config->format,
5374 channel_count,
5375 is_low_latency);
5376 in->config.period_size = buffer_size / frame_size;
5377 }
5378
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005379#ifndef COMPRESS_VOIP_ENABLED
5380 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5381 (in->config.rate == 8000 || in->config.rate == 16000 ||
5382 in->config.rate == 32000 || in->config.rate == 48000) &&
5383 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5384
5385 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5386 in->config = default_pcm_config_voip_copp;
5387 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5388 in->config.rate = in->sample_rate;
5389#else
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005390 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08005391 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005392 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005393 (in->config.rate == 8000 || in->config.rate == 16000 ||
5394 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005395 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5396 voice_extn_compress_voip_open_input_stream(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005397#endif
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005398 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005399 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005400
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305401 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5402 &adev->streams_input_cfg_list,
5403 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305404 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305405
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005406 /* This stream could be for sound trigger lab,
5407 get sound trigger pcm if present */
5408 audio_extn_sound_trigger_check_and_get_session(in);
5409
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305410 lock_input_stream(in);
5411 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5412 pthread_mutex_lock(&adev->lock);
5413 in->card_status = adev->card_status;
5414 pthread_mutex_unlock(&adev->lock);
5415 pthread_mutex_unlock(&in->lock);
5416
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005417 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005418 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005419 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005420
5421err_open:
5422 free(in);
5423 *stream_in = NULL;
5424 return ret;
5425}
5426
5427static void adev_close_input_stream(struct audio_hw_device *dev,
5428 struct audio_stream_in *stream)
5429{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005430 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005431 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005432 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305433
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305434 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005435
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305436 // must deregister from sndmonitor first to prevent races
5437 // between the callback and close_stream
5438 audio_extn_snd_mon_unregister_listener(stream);
5439
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305440 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005441 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305442
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005443 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305444 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005445 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305446 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005447 if (ret != 0)
5448 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5449 __func__, ret);
5450 } else
5451 in_standby(&stream->common);
5452
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005453 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005454 audio_extn_ssr_deinit();
5455 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005456
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305457 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005458 audio_extn_compr_cap_format_supported(in->config.format))
5459 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305460
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305461 if (audio_extn_cin_attached_usecase(in->usecase))
5462 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005463
Mingming Yinfd7607b2016-01-22 12:48:44 -08005464 if (in->is_st_session) {
5465 ALOGV("%s: sound trigger pcm stop lab", __func__);
5466 audio_extn_sound_trigger_stop_lab(in);
5467 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005468 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005469 return;
5470}
5471
Siddartha Shaik31b530e2017-05-19 15:26:33 +05305472int adev_create_audio_patch(struct audio_hw_device *dev,
5473 unsigned int num_sources,
5474 const struct audio_port_config *sources,
5475 unsigned int num_sinks,
5476 const struct audio_port_config *sinks,
5477 audio_patch_handle_t *handle)
5478{
5479
5480
5481 return audio_extn_hw_loopback_create_audio_patch(dev,
5482 num_sources,
5483 sources,
5484 num_sinks,
5485 sinks,
5486 handle);
5487
5488}
5489
5490int adev_release_audio_patch(struct audio_hw_device *dev,
5491 audio_patch_handle_t handle)
5492{
5493 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
5494}
5495
5496int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
5497{
5498 return audio_extn_hw_loopback_get_audio_port(dev, config);
5499}
5500
5501int adev_set_audio_port_config(struct audio_hw_device *dev,
5502 const struct audio_port_config *config)
5503{
5504 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
5505}
5506
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005507static int adev_dump(const audio_hw_device_t *device __unused,
5508 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005509{
5510 return 0;
5511}
5512
5513static int adev_close(hw_device_t *device)
5514{
5515 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005516
5517 if (!adev)
5518 return 0;
5519
5520 pthread_mutex_lock(&adev_init_lock);
5521
5522 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305523 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005524 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005525 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305526 audio_extn_utils_release_streams_cfg_lists(
5527 &adev->streams_output_cfg_list,
5528 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305529 if (audio_extn_qaf_is_enabled())
5530 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005531 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005532 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005533 free(adev->snd_dev_ref_cnt);
5534 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005535 if (adev->adm_deinit)
5536 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305537 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005538 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305539 audio_extn_snd_mon_deinit();
Siddartha Shaik31b530e2017-05-19 15:26:33 +05305540 audio_extn_loopback_deinit(adev);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05305541 if (adev->device_cfg_params) {
5542 free(adev->device_cfg_params);
5543 adev->device_cfg_params = NULL;
5544 }
Kiran Kandi910e1862013-10-29 13:29:42 -07005545 free(device);
5546 adev = NULL;
5547 }
5548 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005550 return 0;
5551}
5552
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005553/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5554 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5555 * just that it _might_ work.
5556 */
5557static int period_size_is_plausible_for_low_latency(int period_size)
5558{
5559 switch (period_size) {
5560 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005561 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005562 case 240:
5563 case 320:
5564 case 480:
5565 return 1;
5566 default:
5567 return 0;
5568 }
5569}
5570
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305571static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
5572{
5573 bool is_snd_card_status = false;
5574 bool is_ext_device_status = false;
5575 char value[32];
5576 int card = -1;
5577 card_status_t status;
5578
5579 if (cookie != adev || !parms)
5580 return;
5581
5582 if (!parse_snd_card_status(parms, &card, &status)) {
5583 is_snd_card_status = true;
5584 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
5585 is_ext_device_status = true;
5586 } else {
5587 // not a valid event
5588 return;
5589 }
5590
5591 pthread_mutex_lock(&adev->lock);
5592 if (card == adev->snd_card || is_ext_device_status) {
5593 if (is_snd_card_status && adev->card_status != status) {
5594 adev->card_status = status;
5595 platform_snd_card_update(adev->platform, status);
5596 audio_extn_fm_set_parameters(adev, parms);
5597 } else if (is_ext_device_status) {
5598 platform_set_parameters(adev->platform, parms);
5599 }
5600 }
5601 pthread_mutex_unlock(&adev->lock);
5602 return;
5603}
5604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005605static int adev_open(const hw_module_t *module, const char *name,
5606 hw_device_t **device)
5607{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305608 int ret;
5609
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005610 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005611 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5612
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005613 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005614 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005615 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005616 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005617 ALOGD("%s: returning existing instance of adev", __func__);
5618 ALOGD("%s: exit", __func__);
5619 pthread_mutex_unlock(&adev_init_lock);
5620 return 0;
5621 }
5622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005623 adev = calloc(1, sizeof(struct audio_device));
5624
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005625 if (!adev) {
5626 pthread_mutex_unlock(&adev_init_lock);
5627 return -ENOMEM;
5628 }
5629
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005630 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5631
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05305632#ifdef DYNAMIC_LOG_ENABLED
5633 register_for_dynamic_logging("hal");
5634#endif
5635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005636 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5637 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5638 adev->device.common.module = (struct hw_module_t *)module;
5639 adev->device.common.close = adev_close;
5640
5641 adev->device.init_check = adev_init_check;
5642 adev->device.set_voice_volume = adev_set_voice_volume;
5643 adev->device.set_master_volume = adev_set_master_volume;
5644 adev->device.get_master_volume = adev_get_master_volume;
5645 adev->device.set_master_mute = adev_set_master_mute;
5646 adev->device.get_master_mute = adev_get_master_mute;
5647 adev->device.set_mode = adev_set_mode;
5648 adev->device.set_mic_mute = adev_set_mic_mute;
5649 adev->device.get_mic_mute = adev_get_mic_mute;
5650 adev->device.set_parameters = adev_set_parameters;
5651 adev->device.get_parameters = adev_get_parameters;
5652 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5653 adev->device.open_output_stream = adev_open_output_stream;
5654 adev->device.close_output_stream = adev_close_output_stream;
5655 adev->device.open_input_stream = adev_open_input_stream;
5656 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05305657 adev->device.create_audio_patch = adev_create_audio_patch;
5658 adev->device.release_audio_patch = adev_release_audio_patch;
5659 adev->device.get_audio_port = adev_get_audio_port;
5660 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005661 adev->device.dump = adev_dump;
5662
5663 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005664 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005665 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005666 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005667 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005668 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005669 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005670 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305671 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005672 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005673 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005674 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005675 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005676 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005677 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305678 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305679 adev->perf_lock_opts[0] = 0x101;
5680 adev->perf_lock_opts[1] = 0x20E;
5681 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305682
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005683 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005684 adev->platform = platform_init(adev);
5685 if (!adev->platform) {
5686 free(adev->snd_dev_ref_cnt);
5687 free(adev);
5688 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5689 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005690 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305691 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005692 return -EINVAL;
5693 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005694
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305695 if (audio_extn_qaf_is_enabled()) {
5696 ret = audio_extn_qaf_init(adev);
5697 if (ret < 0) {
5698 free(adev);
5699 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5700 *device = NULL;
5701 pthread_mutex_unlock(&adev_init_lock);
5702 pthread_mutex_destroy(&adev->lock);
5703 return ret;
5704 }
5705
5706 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5707 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5708 }
5709
Eric Laurentc4aef752013-09-12 17:45:53 -07005710 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5711 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5712 if (adev->visualizer_lib == NULL) {
5713 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5714 } else {
5715 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5716 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005717 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005718 "visualizer_hal_start_output");
5719 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005720 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005721 "visualizer_hal_stop_output");
5722 }
5723 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305724 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005725 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005726 audio_extn_gef_init(adev);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05305727 audio_extn_loopback_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005728
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005729 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5730 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5731 if (adev->offload_effects_lib == NULL) {
5732 ALOGE("%s: DLOPEN failed for %s", __func__,
5733 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5734 } else {
5735 ALOGV("%s: DLOPEN successful for %s", __func__,
5736 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5737 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305738 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005739 "offload_effects_bundle_hal_start_output");
5740 adev->offload_effects_stop_output =
5741 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5742 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005743 adev->offload_effects_set_hpx_state =
5744 (int (*)(bool))dlsym(adev->offload_effects_lib,
5745 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305746 adev->offload_effects_get_parameters =
5747 (void (*)(struct str_parms *, struct str_parms *))
5748 dlsym(adev->offload_effects_lib,
5749 "offload_effects_bundle_get_parameters");
5750 adev->offload_effects_set_parameters =
5751 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5752 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005753 }
5754 }
5755
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005756 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5757 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5758 if (adev->adm_lib == NULL) {
5759 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5760 } else {
5761 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5762 adev->adm_init = (adm_init_t)
5763 dlsym(adev->adm_lib, "adm_init");
5764 adev->adm_deinit = (adm_deinit_t)
5765 dlsym(adev->adm_lib, "adm_deinit");
5766 adev->adm_register_input_stream = (adm_register_input_stream_t)
5767 dlsym(adev->adm_lib, "adm_register_input_stream");
5768 adev->adm_register_output_stream = (adm_register_output_stream_t)
5769 dlsym(adev->adm_lib, "adm_register_output_stream");
5770 adev->adm_deregister_stream = (adm_deregister_stream_t)
5771 dlsym(adev->adm_lib, "adm_deregister_stream");
5772 adev->adm_request_focus = (adm_request_focus_t)
5773 dlsym(adev->adm_lib, "adm_request_focus");
5774 adev->adm_abandon_focus = (adm_abandon_focus_t)
5775 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005776 adev->adm_set_config = (adm_set_config_t)
5777 dlsym(adev->adm_lib, "adm_set_config");
5778 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5779 dlsym(adev->adm_lib, "adm_request_focus_v2");
5780 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5781 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5782 adev->adm_on_routing_change = (adm_on_routing_change_t)
5783 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005784 }
5785 }
5786
Mingming Yin514a8bc2014-07-29 15:22:21 -07005787 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005788 //initialize this to false for now,
5789 //this will be set to true through set param
5790 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005791
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005792 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005793 *device = &adev->device.common;
5794
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305795 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5796 &adev->streams_output_cfg_list,
5797 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005798
Kiran Kandi910e1862013-10-29 13:29:42 -07005799 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005800
5801 char value[PROPERTY_VALUE_MAX];
5802 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005803 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005804 trial = atoi(value);
5805 if (period_size_is_plausible_for_low_latency(trial)) {
5806 pcm_config_low_latency.period_size = trial;
5807 pcm_config_low_latency.start_threshold = trial / 4;
5808 pcm_config_low_latency.avail_min = trial / 4;
5809 configured_low_latency_capture_period_size = trial;
5810 }
5811 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005812 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005813 trial = atoi(value);
5814 if (period_size_is_plausible_for_low_latency(trial)) {
5815 configured_low_latency_capture_period_size = trial;
5816 }
5817 }
5818
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005819 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005820 af_period_multiplier = atoi(value);
5821 if (af_period_multiplier < 0)
5822 af_period_multiplier = 2;
5823 else if (af_period_multiplier > 4)
5824 af_period_multiplier = 4;
5825
5826 ALOGV("new period_multiplier = %d", af_period_multiplier);
5827 }
5828
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005829 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005830 pthread_mutex_unlock(&adev_init_lock);
5831
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005832 if (adev->adm_init)
5833 adev->adm_data = adev->adm_init();
5834
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305835 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305836 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005837 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305838
5839 audio_extn_snd_mon_init();
5840 pthread_mutex_lock(&adev->lock);
5841 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
5842 adev->card_status = CARD_STATUS_ONLINE;
5843 pthread_mutex_unlock(&adev->lock);
5844 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05305845 /* Allocate memory for Device config params */
5846 adev->device_cfg_params = (struct audio_device_config_param*)
5847 calloc(platform_get_max_codec_backend(),
5848 sizeof(struct audio_device_config_param));
5849 if (adev->device_cfg_params == NULL)
5850 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305851
Eric Laurent994a6932013-07-17 11:51:42 -07005852 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005853 return 0;
5854}
5855
5856static struct hw_module_methods_t hal_module_methods = {
5857 .open = adev_open,
5858};
5859
5860struct audio_module HAL_MODULE_INFO_SYM = {
5861 .common = {
5862 .tag = HARDWARE_MODULE_TAG,
5863 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5864 .hal_api_version = HARDWARE_HAL_API_VERSION,
5865 .id = AUDIO_HARDWARE_MODULE_ID,
5866 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005867 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005868 .methods = &hal_module_methods,
5869 },
5870};