blob: 3d3a5d7c03dd1cdaae5ef09410681106302a203f [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
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053089#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070090
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070091#define PROXY_OPEN_RETRY_COUNT 100
92#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080093
Mingming Yin08c7e312015-03-16 18:10:58 -070094#ifdef USE_LL_AS_PRIMARY_OUTPUT
95#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
96#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
97#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080098#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070099#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
100#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800101
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700102#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
103
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700104static unsigned int configured_low_latency_capture_period_size =
105 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
106
Eric Laurentb23d5282013-05-14 15:27:20 -0700107struct pcm_config pcm_config_deep_buffer = {
108 .channels = 2,
109 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
110 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
111 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
112 .format = PCM_FORMAT_S16_LE,
113 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
114 .stop_threshold = INT_MAX,
115 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
116};
117
118struct pcm_config pcm_config_low_latency = {
119 .channels = 2,
120 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
121 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
122 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
123 .format = PCM_FORMAT_S16_LE,
124 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
125 .stop_threshold = INT_MAX,
126 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
127};
128
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700129static int af_period_multiplier = 4;
130struct pcm_config pcm_config_rt = {
131 .channels = 2,
132 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
133 .period_size = ULL_PERIOD_SIZE, //1 ms
134 .period_count = 512, //=> buffer size is 512ms
135 .format = PCM_FORMAT_S16_LE,
136 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
137 .stop_threshold = INT_MAX,
138 .silence_threshold = 0,
139 .silence_size = 0,
140 .avail_min = ULL_PERIOD_SIZE, //1 ms
141};
142
Eric Laurentb23d5282013-05-14 15:27:20 -0700143struct pcm_config pcm_config_hdmi_multi = {
144 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
145 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
146 .period_size = HDMI_MULTI_PERIOD_SIZE,
147 .period_count = HDMI_MULTI_PERIOD_COUNT,
148 .format = PCM_FORMAT_S16_LE,
149 .start_threshold = 0,
150 .stop_threshold = INT_MAX,
151 .avail_min = 0,
152};
153
154struct pcm_config pcm_config_audio_capture = {
155 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700156 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
157 .format = PCM_FORMAT_S16_LE,
158};
159
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700160struct pcm_config pcm_config_audio_capture_rt = {
161 .channels = 2,
162 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
163 .period_size = ULL_PERIOD_SIZE,
164 .period_count = 512,
165 .format = PCM_FORMAT_S16_LE,
166 .start_threshold = 0,
167 .stop_threshold = INT_MAX,
168 .silence_threshold = 0,
169 .silence_size = 0,
170 .avail_min = ULL_PERIOD_SIZE, //1 ms
171};
172
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700173#define AFE_PROXY_CHANNEL_COUNT 2
174#define AFE_PROXY_SAMPLING_RATE 48000
175
176#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
177#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
178
179struct pcm_config pcm_config_afe_proxy_playback = {
180 .channels = AFE_PROXY_CHANNEL_COUNT,
181 .rate = AFE_PROXY_SAMPLING_RATE,
182 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
183 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
186 .stop_threshold = INT_MAX,
187 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
188};
189
190#define AFE_PROXY_RECORD_PERIOD_SIZE 768
191#define AFE_PROXY_RECORD_PERIOD_COUNT 4
192
193struct pcm_config pcm_config_afe_proxy_record = {
194 .channels = AFE_PROXY_CHANNEL_COUNT,
195 .rate = AFE_PROXY_SAMPLING_RATE,
196 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
197 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
198 .format = PCM_FORMAT_S16_LE,
199 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
200 .stop_threshold = INT_MAX,
201 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
202};
203
Ashish Jainf1eaa582016-05-23 20:54:24 +0530204#define AUDIO_MAX_PCM_FORMATS 7
205
206const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
207 [AUDIO_FORMAT_DEFAULT] = 0,
208 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
209 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
210 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
211 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
212 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
213 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
214};
215
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800216const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700217 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
218 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700219 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
220 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700221 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700222 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700223 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
227 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
228 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
229 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
230 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700231
Eric Laurentb23d5282013-05-14 15:27:20 -0700232 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700233 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530234 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
235 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
236 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700237 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700238 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700239 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800240 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800241 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700242 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700243
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700244 [USECASE_VOICE2_CALL] = "voice2-call",
245 [USECASE_VOLTE_CALL] = "volte-call",
246 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800247 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800248 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
249 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800250 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700251 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
252 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
253 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800254 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
255 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
256 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
257
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700258 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
259 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700260 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
261 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700262
263 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
264 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700265 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700266};
267
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700268static const audio_usecase_t offload_usecases[] = {
269 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700270 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
271 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
272 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
273 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
274 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
275 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
276 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
277 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700278};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800279
280#define STRING_TO_ENUM(string) { #string, string }
281
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800282struct string_to_enum {
283 const char *name;
284 uint32_t value;
285};
286
287static const struct string_to_enum out_channels_name_to_enum_table[] = {
288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800289 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
290 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
291 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700292 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800293 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
294 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800295 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
296};
297
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700298static const struct string_to_enum out_formats_name_to_enum_table[] = {
299 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
300 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
301 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700302 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800303 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
304 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700305 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800306};
307
308//list of all supported sample rates by HDMI specification.
309static const int out_hdmi_sample_rates[] = {
310 32000, 44100, 48000, 88200, 96000, 176400, 192000,
311};
312
313static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
314 STRING_TO_ENUM(32000),
315 STRING_TO_ENUM(44100),
316 STRING_TO_ENUM(48000),
317 STRING_TO_ENUM(88200),
318 STRING_TO_ENUM(96000),
319 STRING_TO_ENUM(176400),
320 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700321};
322
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700323static struct audio_device *adev = NULL;
324static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700325static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700326//cache last MBDRC cal step level
327static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700328
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700329static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
330 int flags __unused)
331{
332 int dir = 0;
333 switch (uc_id) {
334 case USECASE_AUDIO_RECORD_LOW_LATENCY:
335 dir = 1;
336 case USECASE_AUDIO_PLAYBACK_ULL:
337 break;
338 default:
339 return false;
340 }
341
342 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
343 PCM_PLAYBACK : PCM_CAPTURE);
344 if (adev->adm_is_noirq_avail)
345 return adev->adm_is_noirq_avail(adev->adm_data,
346 adev->snd_card, dev_id, dir);
347 return false;
348}
349
350static void register_out_stream(struct stream_out *out)
351{
352 struct audio_device *adev = out->dev;
353 if (is_offload_usecase(out->usecase) ||
354 !adev->adm_register_output_stream)
355 return;
356
357 // register stream first for backward compatibility
358 adev->adm_register_output_stream(adev->adm_data,
359 out->handle,
360 out->flags);
361
362 if (!adev->adm_set_config)
363 return;
364
365 if (out->realtime)
366 adev->adm_set_config(adev->adm_data,
367 out->handle,
368 out->pcm, &out->config);
369}
370
371static void register_in_stream(struct stream_in *in)
372{
373 struct audio_device *adev = in->dev;
374 if (!adev->adm_register_input_stream)
375 return;
376
377 adev->adm_register_input_stream(adev->adm_data,
378 in->capture_handle,
379 in->flags);
380
381 if (!adev->adm_set_config)
382 return;
383
384 if (in->realtime)
385 adev->adm_set_config(adev->adm_data,
386 in->capture_handle,
387 in->pcm,
388 &in->config);
389}
390
391static void request_out_focus(struct stream_out *out, long ns)
392{
393 struct audio_device *adev = out->dev;
394
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700395 if (adev->adm_request_focus_v2)
396 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
397 else if (adev->adm_request_focus)
398 adev->adm_request_focus(adev->adm_data, out->handle);
399}
400
401static void request_in_focus(struct stream_in *in, long ns)
402{
403 struct audio_device *adev = in->dev;
404
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700405 if (adev->adm_request_focus_v2)
406 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
407 else if (adev->adm_request_focus)
408 adev->adm_request_focus(adev->adm_data, in->capture_handle);
409}
410
411static void release_out_focus(struct stream_out *out)
412{
413 struct audio_device *adev = out->dev;
414
415 if (adev->adm_abandon_focus)
416 adev->adm_abandon_focus(adev->adm_data, out->handle);
417}
418
419static void release_in_focus(struct stream_in *in)
420{
421 struct audio_device *adev = in->dev;
422 if (adev->adm_abandon_focus)
423 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
424}
425
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530426static int parse_snd_card_status(struct str_parms *parms, int *card,
427 card_status_t *status)
428{
429 char value[32]={0};
430 char state[32]={0};
431
432 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
433 if (ret < 0)
434 return -1;
435
436 // sscanf should be okay as value is of max length 32.
437 // same as sizeof state.
438 if (sscanf(value, "%d,%s", card, state) < 2)
439 return -1;
440
441 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
442 CARD_STATUS_OFFLINE;
443 return 0;
444}
445
vivek mehtaa76401a2015-04-24 14:12:15 -0700446__attribute__ ((visibility ("default")))
447bool audio_hw_send_gain_dep_calibration(int level) {
448 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700449 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700450
451 pthread_mutex_lock(&adev_init_lock);
452
453 if (adev != NULL && adev->platform != NULL) {
454 pthread_mutex_lock(&adev->lock);
455 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700456
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530457 // cache level info for any of the use case which
458 // was not started.
459 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700460
vivek mehtaa76401a2015-04-24 14:12:15 -0700461 pthread_mutex_unlock(&adev->lock);
462 } else {
463 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
464 }
465
466 pthread_mutex_unlock(&adev_init_lock);
467
468 return ret_val;
469}
470
Ashish Jain5106d362016-05-11 19:23:33 +0530471static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
472{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800473 bool gapless_enabled = false;
474 const char *mixer_ctl_name = "Compress Gapless Playback";
475 struct mixer_ctl *ctl;
476
477 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700478 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530479
480 /*Disable gapless if its AV playback*/
481 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800482
483 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
484 if (!ctl) {
485 ALOGE("%s: Could not get ctl for mixer cmd - %s",
486 __func__, mixer_ctl_name);
487 return -EINVAL;
488 }
489
490 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
491 ALOGE("%s: Could not set gapless mode %d",
492 __func__, gapless_enabled);
493 return -EINVAL;
494 }
495 return 0;
496}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700497
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700498__attribute__ ((visibility ("default")))
499int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
500 int table_size) {
501 int ret_val = 0;
502 ALOGV("%s: enter ... ", __func__);
503
504 pthread_mutex_lock(&adev_init_lock);
505 if (adev == NULL) {
506 ALOGW("%s: adev is NULL .... ", __func__);
507 goto done;
508 }
509
510 pthread_mutex_lock(&adev->lock);
511 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
512 pthread_mutex_unlock(&adev->lock);
513done:
514 pthread_mutex_unlock(&adev_init_lock);
515 ALOGV("%s: exit ... ", __func__);
516 return ret_val;
517}
518
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700519static bool is_supported_format(audio_format_t format)
520{
Eric Laurent86e17132013-09-12 17:49:30 -0700521 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530522 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530523 format == AUDIO_FORMAT_AAC_LC ||
524 format == AUDIO_FORMAT_AAC_HE_V1 ||
525 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530526 format == AUDIO_FORMAT_AAC_ADTS_LC ||
527 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
528 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530529 format == AUDIO_FORMAT_AAC_LATM_LC ||
530 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
531 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530532 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
533 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530534 format == AUDIO_FORMAT_PCM_FLOAT ||
535 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700536 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530537 format == AUDIO_FORMAT_AC3 ||
538 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700539 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530540 format == AUDIO_FORMAT_DTS ||
541 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800542 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530543 format == AUDIO_FORMAT_ALAC ||
544 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530545 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530546 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800547 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530548 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700549 format == AUDIO_FORMAT_APTX ||
550 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800551 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700552
553 return false;
554}
555
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700556static inline bool is_mmap_usecase(audio_usecase_t uc_id)
557{
558 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
559 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
560}
561
Avinash Vaish71a8b972014-07-24 15:36:33 +0530562static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
563 struct audio_usecase *uc_info)
564{
565 struct listnode *node;
566 struct audio_usecase *usecase;
567
568 if (uc_info == NULL)
569 return -EINVAL;
570
571 /* Re-route all voice usecases on the shared backend other than the
572 specified usecase to new snd devices */
573 list_for_each(node, &adev->usecase_list) {
574 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800575 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530576 enable_audio_route(adev, usecase);
577 }
578 return 0;
579}
580
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530581static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530582{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530583 ALOGV("%s", __func__);
584 audio_route_apply_and_update_path(adev->audio_route,
585 "asrc-mode");
586 adev->asrc_mode_enabled = true;
587}
588
589static void disable_asrc_mode(struct audio_device *adev)
590{
591 ALOGV("%s", __func__);
592 audio_route_reset_and_update_path(adev->audio_route,
593 "asrc-mode");
594 adev->asrc_mode_enabled = false;
595}
596
597/*
598 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
599 * 44.1 or Native DSD backends are enabled for any of current use case.
600 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
601 * - Disable current mix path use case(Headphone backend) and re-enable it with
602 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
603 * e.g. Naitve DSD or Headphone 44.1 -> + 48
604 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530605static void check_and_set_asrc_mode(struct audio_device *adev,
606 struct audio_usecase *uc_info,
607 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530608{
609 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530610 int i, num_new_devices = 0;
611 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
612 /*
613 *Split snd device for new combo use case
614 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
615 */
616 if (platform_split_snd_device(adev->platform,
617 snd_device,
618 &num_new_devices,
619 split_new_snd_devices) == 0) {
620 for (i = 0; i < num_new_devices; i++)
621 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
622 } else {
623 int new_backend_idx = platform_get_backend_index(snd_device);
624 if (((new_backend_idx == HEADPHONE_BACKEND) ||
625 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
626 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
627 !adev->asrc_mode_enabled) {
628 struct listnode *node = NULL;
629 struct audio_usecase *uc = NULL;
630 struct stream_out *curr_out = NULL;
631 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
632 int i, num_devices, ret = 0;
633 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530634
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530635 list_for_each(node, &adev->usecase_list) {
636 uc = node_to_item(node, struct audio_usecase, list);
637 curr_out = (struct stream_out*) uc->stream.out;
638 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
639 /*
640 *Split snd device for existing combo use case
641 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
642 */
643 ret = platform_split_snd_device(adev->platform,
644 uc->out_snd_device,
645 &num_devices,
646 split_snd_devices);
647 if (ret < 0 || num_devices == 0) {
648 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
649 split_snd_devices[0] = uc->out_snd_device;
650 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800651 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530652 for (i = 0; i < num_devices; i++) {
653 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
654 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
655 if((new_backend_idx == HEADPHONE_BACKEND) &&
656 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
657 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
658 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
659 __func__);
660 enable_asrc_mode(adev);
661 break;
662 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
663 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
664 (usecase_backend_idx == HEADPHONE_BACKEND)) {
665 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
666 __func__);
667 disable_audio_route(adev, uc);
668 disable_snd_device(adev, uc->out_snd_device);
669 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
670 if (new_backend_idx == DSD_NATIVE_BACKEND)
671 audio_route_apply_and_update_path(adev->audio_route,
672 "hph-true-highquality-mode");
673 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
674 (curr_out->bit_width >= 24))
675 audio_route_apply_and_update_path(adev->audio_route,
676 "hph-highquality-mode");
677 enable_asrc_mode(adev);
678 enable_snd_device(adev, uc->out_snd_device);
679 enable_audio_route(adev, uc);
680 break;
681 }
682 }
683 // reset split devices count
684 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800685 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530686 if (adev->asrc_mode_enabled)
687 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530688 }
689 }
690 }
691}
692
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700693int pcm_ioctl(struct pcm *pcm, int request, ...)
694{
695 va_list ap;
696 void * arg;
697 int pcm_fd = *(int*)pcm;
698
699 va_start(ap, request);
700 arg = va_arg(ap, void *);
701 va_end(ap);
702
703 return ioctl(pcm_fd, request, arg);
704}
705
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700706int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700707 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800708{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700709 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700710 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530711 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800712
713 if (usecase == NULL)
714 return -EINVAL;
715
716 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
717
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800718 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700719 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800720 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700721 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800722
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800723#ifdef DS1_DOLBY_DAP_ENABLED
724 audio_extn_dolby_set_dmid(adev);
725 audio_extn_dolby_set_endpoint(adev);
726#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700727 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700728 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530729 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700730 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530731 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530732 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
733 out = usecase->stream.out;
734 if (out && out->compr)
735 audio_extn_utils_compress_set_clk_rec_mode(usecase);
736 }
737
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800738 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700739 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700740 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700741 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800742 ALOGV("%s: exit", __func__);
743 return 0;
744}
745
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700746int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700747 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800748{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700749 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700750 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800751
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530752 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800753 return -EINVAL;
754
755 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700756 if (usecase->type == PCM_CAPTURE)
757 snd_device = usecase->in_snd_device;
758 else
759 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800760 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700761 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700762 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700763 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700764 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530765 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800766 ALOGV("%s: exit", __func__);
767 return 0;
768}
769
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700770int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700771 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800772{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530773 int i, num_devices = 0;
774 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700775 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
776
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800777 if (snd_device < SND_DEVICE_MIN ||
778 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800779 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800780 return -EINVAL;
781 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700782
783 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700784
785 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
786 ALOGE("%s: Invalid sound device returned", __func__);
787 return -EINVAL;
788 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700789 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700790 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700791 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700792 return 0;
793 }
794
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530795
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700796 if (audio_extn_spkr_prot_is_enabled())
797 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700798
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800799 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
800 audio_extn_spkr_prot_is_enabled()) {
801 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700802 adev->snd_dev_ref_cnt[snd_device]--;
803 return -EINVAL;
804 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200805 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800806 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800807 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200808 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800809 return -EINVAL;
810 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700811 } else if (platform_split_snd_device(adev->platform,
812 snd_device,
813 &num_devices,
814 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530815 for (i = 0; i < num_devices; i++) {
816 enable_snd_device(adev, new_snd_devices[i]);
817 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800818 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700819 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530820
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530821
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530822 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
823 (audio_extn_a2dp_start_playback() < 0)) {
824 ALOGE(" fail to configure A2dp control path ");
825 return -EINVAL;
826 }
827
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700828 /* due to the possibility of calibration overwrite between listen
829 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700830 audio_extn_sound_trigger_update_device_status(snd_device,
831 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530832 audio_extn_listen_update_device_status(snd_device,
833 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700834 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700835 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700836 audio_extn_sound_trigger_update_device_status(snd_device,
837 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530838 audio_extn_listen_update_device_status(snd_device,
839 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700840 return -EINVAL;
841 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300842 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700843 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530844
845 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
846 !adev->native_playback_enabled &&
847 audio_is_true_native_stream_active(adev)) {
848 ALOGD("%s: %d: napb: enabling native mode in hardware",
849 __func__, __LINE__);
850 audio_route_apply_and_update_path(adev->audio_route,
851 "true-native-mode");
852 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530853 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800854 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800855 return 0;
856}
857
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700858int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700859 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800860{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530861 int i, num_devices = 0;
862 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700863 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
864
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800865 if (snd_device < SND_DEVICE_MIN ||
866 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800867 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800868 return -EINVAL;
869 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700870 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
871 ALOGE("%s: device ref cnt is already 0", __func__);
872 return -EINVAL;
873 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700874
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700875 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700876
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700877 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
878 ALOGE("%s: Invalid sound device returned", __func__);
879 return -EINVAL;
880 }
881
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700883 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530884
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800885 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
886 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700887 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700888 } else if (platform_split_snd_device(adev->platform,
889 snd_device,
890 &num_devices,
891 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530892 for (i = 0; i < num_devices; i++) {
893 disable_snd_device(adev, new_snd_devices[i]);
894 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300895 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700896 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300897 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700898
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530899 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
900 audio_extn_a2dp_stop_playback();
901
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700902 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530903 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530904 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
905 adev->native_playback_enabled) {
906 ALOGD("%s: %d: napb: disabling native mode in hardware",
907 __func__, __LINE__);
908 audio_route_reset_and_update_path(adev->audio_route,
909 "true-native-mode");
910 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530911 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
912 adev->asrc_mode_enabled) {
913 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530914 disable_asrc_mode(adev);
915 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530916 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530917
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200918 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700919 audio_extn_sound_trigger_update_device_status(snd_device,
920 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530921 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800922 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700923 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800925 return 0;
926}
927
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700928/*
929 legend:
930 uc - existing usecase
931 new_uc - new usecase
932 d1, d11, d2 - SND_DEVICE enums
933 a1, a2 - corresponding ANDROID device enums
934 B1, B2 - backend strings
935
936case 1
937 uc->dev d1 (a1) B1
938 new_uc->dev d1 (a1), d2 (a2) B1, B2
939
940 resolution: disable and enable uc->dev on d1
941
942case 2
943 uc->dev d1 (a1) B1
944 new_uc->dev d11 (a1) B1
945
946 resolution: need to switch uc since d1 and d11 are related
947 (e.g. speaker and voice-speaker)
948 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
949
950case 3
951 uc->dev d1 (a1) B1
952 new_uc->dev d2 (a2) B2
953
954 resolution: no need to switch uc
955
956case 4
957 uc->dev d1 (a1) B1
958 new_uc->dev d2 (a2) B1
959
960 resolution: disable enable uc-dev on d2 since backends match
961 we cannot enable two streams on two different devices if they
962 share the same backend. e.g. if offload is on speaker device using
963 QUAD_MI2S backend and a low-latency stream is started on voice-handset
964 using the same backend, offload must also be switched to voice-handset.
965
966case 5
967 uc->dev d1 (a1) B1
968 new_uc->dev d1 (a1), d2 (a2) B1
969
970 resolution: disable enable uc-dev on d2 since backends match
971 we cannot enable two streams on two different devices if they
972 share the same backend.
973
974case 6
975 uc->dev d1 (a1) B1
976 new_uc->dev d2 (a1) B2
977
978 resolution: no need to switch
979
980case 7
981 uc->dev d1 (a1), d2 (a2) B1, B2
982 new_uc->dev d1 (a1) B1
983
984 resolution: no need to switch
985
986*/
987static snd_device_t derive_playback_snd_device(void * platform,
988 struct audio_usecase *uc,
989 struct audio_usecase *new_uc,
990 snd_device_t new_snd_device)
991{
992 audio_devices_t a1 = uc->stream.out->devices;
993 audio_devices_t a2 = new_uc->stream.out->devices;
994
995 snd_device_t d1 = uc->out_snd_device;
996 snd_device_t d2 = new_snd_device;
997
998 // Treat as a special case when a1 and a2 are not disjoint
999 if ((a1 != a2) && (a1 & a2)) {
1000 snd_device_t d3[2];
1001 int num_devices = 0;
1002 int ret = platform_split_snd_device(platform,
1003 popcount(a1) > 1 ? d1 : d2,
1004 &num_devices,
1005 d3);
1006 if (ret < 0) {
1007 if (ret != -ENOSYS) {
1008 ALOGW("%s failed to split snd_device %d",
1009 __func__,
1010 popcount(a1) > 1 ? d1 : d2);
1011 }
1012 goto end;
1013 }
1014
1015 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1016 // But if it does happen, we need to give priority to d2 if
1017 // the combo devices active on the existing usecase share a backend.
1018 // This is because we cannot have a usecase active on a combo device
1019 // and a new usecase requests one device in this combo pair.
1020 if (platform_check_backends_match(d3[0], d3[1])) {
1021 return d2; // case 5
1022 } else {
1023 return d1; // case 1
1024 }
1025 } else {
1026 if (platform_check_backends_match(d1, d2)) {
1027 return d2; // case 2, 4
1028 } else {
1029 return d1; // case 6, 3
1030 }
1031 }
1032
1033end:
1034 return d2; // return whatever was calculated before.
1035}
1036
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001037static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301038 struct audio_usecase *uc_info,
1039 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001040{
1041 struct listnode *node;
1042 struct audio_usecase *usecase;
1043 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301044 snd_device_t uc_derive_snd_device;
1045 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001046 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001047 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301048 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049 /*
1050 * This function is to make sure that all the usecases that are active on
1051 * the hardware codec backend are always routed to any one device that is
1052 * handled by the hardware codec.
1053 * For example, if low-latency and deep-buffer usecases are currently active
1054 * on speaker and out_set_parameters(headset) is received on low-latency
1055 * output, then we have to make sure deep-buffer is also switched to headset,
1056 * because of the limitation that both the devices cannot be enabled
1057 * at the same time as they share the same backend.
1058 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001059 /*
1060 * This call is to check if we need to force routing for a particular stream
1061 * If there is a backend configuration change for the device when a
1062 * new stream starts, then ADM needs to be closed and re-opened with the new
1063 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001064 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001065 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001066 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1067 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301068 /* For a2dp device reconfigure all active sessions
1069 * with new AFE encoder format based on a2dp state
1070 */
1071 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1072 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1073 audio_extn_a2dp_is_force_device_switch()) {
1074 force_routing = true;
1075 force_restart_session = true;
1076 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301077 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1078
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001079 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001080 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001081 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001082 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1083 switch_device[i] = false;
1084
1085 list_for_each(node, &adev->usecase_list) {
1086 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001087
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301088 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1089 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301090 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301091 platform_get_snd_device_name(usecase->out_snd_device),
1092 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301093 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1094 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1095 usecase, uc_info, snd_device);
1096 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1097 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1098 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1099 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1100 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1101 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1102 ((force_restart_session) ||
1103 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301104 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1105 __func__, use_case_table[usecase->id],
1106 platform_get_snd_device_name(usecase->out_snd_device));
1107 disable_audio_route(adev, usecase);
1108 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301109 /* Enable existing usecase on derived playback device */
1110 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301111 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301112 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001113 }
1114 }
1115
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301116 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1117 num_uc_to_switch);
1118
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001119 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001120 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001121
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301122 /* Make sure the previous devices to be disabled first and then enable the
1123 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001124 list_for_each(node, &adev->usecase_list) {
1125 usecase = node_to_item(node, struct audio_usecase, list);
1126 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001127 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128 }
1129 }
1130
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001131 list_for_each(node, &adev->usecase_list) {
1132 usecase = node_to_item(node, struct audio_usecase, list);
1133 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301134 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001135 }
1136 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001138 /* Re-route all the usecases on the shared backend other than the
1139 specified usecase to new snd devices */
1140 list_for_each(node, &adev->usecase_list) {
1141 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301142 /* Update the out_snd_device only before enabling the audio route */
1143 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301144 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301145 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301146 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301147 use_case_table[usecase->id],
1148 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001149 /* Update voc calibration before enabling VoIP route */
1150 if (usecase->type == VOIP_CALL)
1151 status = platform_switch_voice_call_device_post(adev->platform,
1152 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001153 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301154 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301155 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001156 }
1157 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001158 }
1159}
1160
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301161static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001162 struct audio_usecase *uc_info,
1163 snd_device_t snd_device)
1164{
1165 struct listnode *node;
1166 struct audio_usecase *usecase;
1167 bool switch_device[AUDIO_USECASE_MAX];
1168 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301169 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001170 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001171
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301172 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1173 snd_device);
1174 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301175
1176 /*
1177 * Make sure out devices is checked against out codec backend device and
1178 * also in devices against in codec backend. Checking out device against in
1179 * codec backend or vice versa causes issues.
1180 */
1181 if (uc_info->type == PCM_CAPTURE)
1182 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001183 /*
1184 * This function is to make sure that all the active capture usecases
1185 * are always routed to the same input sound device.
1186 * For example, if audio-record and voice-call usecases are currently
1187 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1188 * is received for voice call then we have to make sure that audio-record
1189 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1190 * because of the limitation that two devices cannot be enabled
1191 * at the same time if they share the same backend.
1192 */
1193 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1194 switch_device[i] = false;
1195
1196 list_for_each(node, &adev->usecase_list) {
1197 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301198 /*
1199 * TODO: Enhance below condition to handle BT sco/USB multi recording
1200 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001201 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001202 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301203 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301204 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301205 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301206 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001207 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001208 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1209 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001210 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001211 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001212 switch_device[usecase->id] = true;
1213 num_uc_to_switch++;
1214 }
1215 }
1216
1217 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001218 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001219
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301220 /* Make sure the previous devices to be disabled first and then enable the
1221 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001222 list_for_each(node, &adev->usecase_list) {
1223 usecase = node_to_item(node, struct audio_usecase, list);
1224 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001225 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001226 }
1227 }
1228
1229 list_for_each(node, &adev->usecase_list) {
1230 usecase = node_to_item(node, struct audio_usecase, list);
1231 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001232 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001233 }
1234 }
1235
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001236 /* Re-route all the usecases on the shared backend other than the
1237 specified usecase to new snd devices */
1238 list_for_each(node, &adev->usecase_list) {
1239 usecase = node_to_item(node, struct audio_usecase, list);
1240 /* Update the in_snd_device only before enabling the audio route */
1241 if (switch_device[usecase->id] ) {
1242 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001243 if (usecase->type != VOICE_CALL) {
1244 /* Update voc calibration before enabling VoIP route */
1245 if (usecase->type == VOIP_CALL)
1246 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001247 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001248 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301249 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001250 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001251 }
1252 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001253 }
1254}
1255
Mingming Yin3a941d42016-02-17 18:08:05 -08001256static void reset_hdmi_sink_caps(struct stream_out *out) {
1257 int i = 0;
1258
1259 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1260 out->supported_channel_masks[i] = 0;
1261 }
1262 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1263 out->supported_formats[i] = 0;
1264 }
1265 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1266 out->supported_sample_rates[i] = 0;
1267 }
1268}
1269
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001270/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001271static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272{
Mingming Yin3a941d42016-02-17 18:08:05 -08001273 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001274 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275
Mingming Yin3a941d42016-02-17 18:08:05 -08001276 reset_hdmi_sink_caps(out);
1277
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001278 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001279 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001280 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001281 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001282 }
1283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001284 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001285 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001286 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001287 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001288 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1289 case 6:
1290 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1291 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1292 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1293 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1294 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1295 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001296 break;
1297 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001298 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001299 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001300 break;
1301 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001302
1303 // check channel format caps
1304 i = 0;
1305 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1306 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1307 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1308 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1309 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1310 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1311 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1312 }
1313
Ben Romberger1aaaf862017-04-06 17:49:46 -07001314 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1315 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1316 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1317 }
1318
Mingming Yin3a941d42016-02-17 18:08:05 -08001319 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1320 ALOGV(":%s HDMI supports DTS format", __func__);
1321 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1322 }
1323
1324 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1325 ALOGV(":%s HDMI supports DTS HD format", __func__);
1326 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1327 }
1328
Naresh Tanniru928f0862017-04-07 16:44:23 -07001329 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1330 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1331 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1332 }
1333
Mingming Yin3a941d42016-02-17 18:08:05 -08001334
1335 // check sample rate caps
1336 i = 0;
1337 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1338 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1339 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1340 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1341 }
1342 }
1343
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001344 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001345}
1346
Alexy Josephb1379942016-01-29 15:49:38 -08001347audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001348 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001349{
1350 struct audio_usecase *usecase;
1351 struct listnode *node;
1352
1353 list_for_each(node, &adev->usecase_list) {
1354 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001355 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001356 ALOGV("%s: usecase id %d", __func__, usecase->id);
1357 return usecase->id;
1358 }
1359 }
1360 return USECASE_INVALID;
1361}
1362
Alexy Josephb1379942016-01-29 15:49:38 -08001363struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001364 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001365{
1366 struct audio_usecase *usecase;
1367 struct listnode *node;
1368
1369 list_for_each(node, &adev->usecase_list) {
1370 usecase = node_to_item(node, struct audio_usecase, list);
1371 if (usecase->id == uc_id)
1372 return usecase;
1373 }
1374 return NULL;
1375}
1376
Dhananjay Kumard4833242016-10-06 22:09:12 +05301377struct stream_in *get_next_active_input(const struct audio_device *adev)
1378{
1379 struct audio_usecase *usecase;
1380 struct listnode *node;
1381
1382 list_for_each_reverse(node, &adev->usecase_list) {
1383 usecase = node_to_item(node, struct audio_usecase, list);
1384 if (usecase->type == PCM_CAPTURE)
1385 return usecase->stream.in;
1386 }
1387 return NULL;
1388}
1389
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301390/*
1391 * is a true native playback active
1392 */
1393bool audio_is_true_native_stream_active(struct audio_device *adev)
1394{
1395 bool active = false;
1396 int i = 0;
1397 struct listnode *node;
1398
1399 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1400 ALOGV("%s:napb: not in true mode or non hdphones device",
1401 __func__);
1402 active = false;
1403 goto exit;
1404 }
1405
1406 list_for_each(node, &adev->usecase_list) {
1407 struct audio_usecase *uc;
1408 uc = node_to_item(node, struct audio_usecase, list);
1409 struct stream_out *curr_out =
1410 (struct stream_out*) uc->stream.out;
1411
1412 if (curr_out && PCM_PLAYBACK == uc->type) {
1413 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1414 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1415 uc->id, curr_out->sample_rate,
1416 curr_out->bit_width,
1417 platform_get_snd_device_name(uc->out_snd_device));
1418
1419 if (is_offload_usecase(uc->id) &&
1420 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1421 active = true;
1422 ALOGD("%s:napb:native stream detected", __func__);
1423 }
1424 }
1425 }
1426exit:
1427 return active;
1428}
1429
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301430/*
1431 * if native DSD playback active
1432 */
1433bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1434{
1435 bool active = false;
1436 struct listnode *node = NULL;
1437 struct audio_usecase *uc = NULL;
1438 struct stream_out *curr_out = NULL;
1439
1440 list_for_each(node, &adev->usecase_list) {
1441 uc = node_to_item(node, struct audio_usecase, list);
1442 curr_out = (struct stream_out*) uc->stream.out;
1443
1444 if (curr_out && PCM_PLAYBACK == uc->type &&
1445 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1446 active = true;
1447 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301448 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301449 }
1450 }
1451 return active;
1452}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301453
1454static bool force_device_switch(struct audio_usecase *usecase)
1455{
1456 bool ret = false;
1457 bool is_it_true_mode = false;
1458
1459 if (is_offload_usecase(usecase->id) &&
1460 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001461 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1462 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1463 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301464 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1465 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1466 (!is_it_true_mode && adev->native_playback_enabled)){
1467 ret = true;
1468 ALOGD("napb: time to toggle native mode");
1469 }
1470 }
1471
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301472 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301473 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1474 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301475 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001476 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301477 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301478 ALOGD("Force a2dp device switch to update new encoder config");
1479 ret = true;
1480 }
1481
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301482 return ret;
1483}
1484
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301485bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1486{
1487 bool ret=false;
1488 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1489 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1490 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1491 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1492 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1493 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1494 ret = true;
1495
1496 return ret;
1497}
1498
1499bool is_a2dp_device(snd_device_t out_snd_device)
1500{
1501 bool ret=false;
1502 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1503 ret = true;
1504
1505 return ret;
1506}
1507
1508bool is_bt_soc_on(struct audio_device *adev)
1509{
1510 struct mixer_ctl *ctl;
1511 char *mixer_ctl_name = "BT SOC status";
1512 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1513 bool bt_soc_status = true;
1514 if (!ctl) {
1515 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1516 __func__, mixer_ctl_name);
1517 /*This is to ensure we dont break targets which dont have the kernel change*/
1518 return true;
1519 }
1520 bt_soc_status = mixer_ctl_get_value(ctl, 0);
1521 ALOGD("BT SOC status: %d",bt_soc_status);
1522 return bt_soc_status;
1523}
1524
1525int out_standby_l(struct audio_stream *stream);
1526
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001527int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001528{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001529 snd_device_t out_snd_device = SND_DEVICE_NONE;
1530 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001531 struct audio_usecase *usecase = NULL;
1532 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001533 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001534 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001535 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001536 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301538 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1539
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001540 usecase = get_usecase_from_list(adev, uc_id);
1541 if (usecase == NULL) {
1542 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1543 return -EINVAL;
1544 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001545
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001546 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001547 (usecase->type == VOIP_CALL) ||
1548 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301549 if(usecase->stream.out == NULL) {
1550 ALOGE("%s: stream.out is NULL", __func__);
1551 return -EINVAL;
1552 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001553 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001554 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001555 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001556 usecase->devices = usecase->stream.out->devices;
1557 } else {
1558 /*
1559 * If the voice call is active, use the sound devices of voice call usecase
1560 * so that it would not result any device switch. All the usecases will
1561 * be switched to new device when select_devices() is called for voice call
1562 * usecase. This is to avoid switching devices for voice call when
1563 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001564 * choose voice call device only if the use case device is
1565 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001566 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001567 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001568 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001569 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001570 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1571 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301572 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1573 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001574 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001575 in_snd_device = vc_usecase->in_snd_device;
1576 out_snd_device = vc_usecase->out_snd_device;
1577 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001578 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001579 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001580 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001581 if ((voip_usecase != NULL) &&
1582 (usecase->type == PCM_PLAYBACK) &&
1583 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001584 out_snd_device_backend_match = platform_check_backends_match(
1585 voip_usecase->out_snd_device,
1586 platform_get_output_snd_device(
1587 adev->platform,
1588 usecase->stream.out));
1589 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001590 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001591 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1592 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001593 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001594 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001595 in_snd_device = voip_usecase->in_snd_device;
1596 out_snd_device = voip_usecase->out_snd_device;
1597 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001598 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001599 hfp_ucid = audio_extn_hfp_get_usecase();
1600 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001601 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001602 in_snd_device = hfp_usecase->in_snd_device;
1603 out_snd_device = hfp_usecase->out_snd_device;
1604 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001605 }
1606 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301607 if (usecase->stream.out == NULL) {
1608 ALOGE("%s: stream.out is NULL", __func__);
1609 return -EINVAL;
1610 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001611 usecase->devices = usecase->stream.out->devices;
1612 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001613 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001614 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001615 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001616 if (usecase->stream.out == adev->primary_output &&
1617 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001618 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001619 select_devices(adev, adev->active_input->usecase);
1620 }
1621 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001622 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301623 if (usecase->stream.in == NULL) {
1624 ALOGE("%s: stream.in is NULL", __func__);
1625 return -EINVAL;
1626 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001627 usecase->devices = usecase->stream.in->device;
1628 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001629 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001630 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001631 if (adev->active_input &&
1632 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301633 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1634 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1635 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001636 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001637 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001638 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1639 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001640 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001641 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001642 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001643 }
1644 }
1645
1646 if (out_snd_device == usecase->out_snd_device &&
1647 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301648
1649 if (!force_device_switch(usecase))
1650 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001651 }
1652
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301653 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
1654 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
1655 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1656 return 0;
1657 }
1658
sangwoobc677242013-08-08 16:53:43 +09001659 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001660 out_snd_device, platform_get_snd_device_name(out_snd_device),
1661 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001663 /*
1664 * Limitation: While in call, to do a device switch we need to disable
1665 * and enable both RX and TX devices though one of them is same as current
1666 * device.
1667 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001668 if ((usecase->type == VOICE_CALL) &&
1669 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1670 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001671 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001672 }
1673
1674 if (((usecase->type == VOICE_CALL) ||
1675 (usecase->type == VOIP_CALL)) &&
1676 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1677 /* Disable sidetone only if voice/voip call already exists */
1678 if (voice_is_call_state_active(adev) ||
1679 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001680 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001681
1682 /* Disable aanc only if voice call exists */
1683 if (voice_is_call_state_active(adev))
1684 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001685 }
1686
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001687 /* Disable current sound devices */
1688 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001689 disable_audio_route(adev, usecase);
1690 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691 }
1692
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001693 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001694 disable_audio_route(adev, usecase);
1695 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696 }
1697
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001698 /* Applicable only on the targets that has external modem.
1699 * New device information should be sent to modem before enabling
1700 * the devices to reduce in-call device switch time.
1701 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001702 if ((usecase->type == VOICE_CALL) &&
1703 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1704 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001705 status = platform_switch_voice_call_enable_device_config(adev->platform,
1706 out_snd_device,
1707 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001708 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001709
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001710 /* Enable new sound devices */
1711 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001712 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301713 if (platform_check_codec_asrc_support(adev->platform))
1714 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001715 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716 }
1717
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001718 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301719 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001720 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001721 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001722
Avinash Vaish71a8b972014-07-24 15:36:33 +05301723 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001724 status = platform_switch_voice_call_device_post(adev->platform,
1725 out_snd_device,
1726 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301727 enable_audio_route_for_voice_usecases(adev, usecase);
1728 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001729
sangwoo170731f2013-06-08 15:36:36 +09001730 usecase->in_snd_device = in_snd_device;
1731 usecase->out_snd_device = out_snd_device;
1732
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301733 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1734 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301735 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001736 if ((24 == usecase->stream.out->bit_width) &&
1737 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1738 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1739 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1740 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1741 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1742 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1743 /*
1744 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1745 * configured device sample rate, if not update the COPP rate to be equal to the
1746 * device sample rate, else open COPP at stream sample rate
1747 */
1748 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1749 usecase->stream.out->sample_rate,
1750 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301751 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1752 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001753 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1754 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1755 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1756 }
1757
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001758 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001759 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001760 audio_extn_gef_notify_device_config(
1761 usecase->stream.out->devices,
1762 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001763 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001764 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001765 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301766 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001767 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001768
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001769 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001770 /* Enable aanc only if voice call exists */
1771 if (voice_is_call_state_active(adev))
1772 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1773
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001774 /* Enable sidetone only if other voice/voip call already exists */
1775 if (voice_is_call_state_active(adev) ||
1776 voice_extn_compress_voip_is_started(adev))
1777 voice_set_sidetone(adev, out_snd_device, true);
1778 }
1779
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001780 /* Applicable only on the targets that has external modem.
1781 * Enable device command should be sent to modem only after
1782 * enabling voice call mixer controls
1783 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001784 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001785 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1786 out_snd_device,
1787 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301788
1789 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
1790
1791 if (usecase->type == VOIP_CALL) {
1792 if (adev->active_input != NULL &&
1793 !adev->active_input->standby) {
1794 if (is_bt_soc_on(adev) == false){
1795 ALOGD("BT SCO MIC disconnected while in connection");
1796 if (adev->active_input->pcm != NULL)
1797 pcm_stop(adev->active_input->pcm);
1798 }
1799 }
1800 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
1801 && usecase->stream.out->started) {
1802 if (is_bt_soc_on(adev) == false) {
1803 ALOGD("BT SCO/A2DP disconnected while in connection");
1804 out_standby_l(&usecase->stream.out->stream.common);
1805 }
1806 }
1807 } else if ((usecase->stream.out != NULL) &&
1808 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
1809 usecase->stream.out->started) {
1810 if (is_bt_soc_on(adev) == false) {
1811 ALOGD("BT SCO/A2dp disconnected while in connection");
1812 out_standby_l(&usecase->stream.out->stream.common);
1813 }
1814 }
1815 }
1816
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301817 ALOGD("%s: done",__func__);
1818
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001819 return status;
1820}
1821
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001822static int stop_input_stream(struct stream_in *in)
1823{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301824 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825 struct audio_usecase *uc_info;
1826 struct audio_device *adev = in->dev;
1827
Eric Laurent994a6932013-07-17 11:51:42 -07001828 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001829 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830 uc_info = get_usecase_from_list(adev, in->usecase);
1831 if (uc_info == NULL) {
1832 ALOGE("%s: Could not find the usecase (%d) in the list",
1833 __func__, in->usecase);
1834 return -EINVAL;
1835 }
1836
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001837 /* Close in-call recording streams */
1838 voice_check_and_stop_incall_rec_usecase(adev, in);
1839
Eric Laurent150dbfe2013-02-27 14:31:02 -08001840 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001841 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001842
1843 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001844 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001846 list_remove(&uc_info->list);
1847 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001848
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001849 adev->active_input = get_next_active_input(adev);
1850
Eric Laurent994a6932013-07-17 11:51:42 -07001851 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852 return ret;
1853}
1854
1855int start_input_stream(struct stream_in *in)
1856{
1857 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001858 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001859 struct audio_usecase *uc_info;
1860 struct audio_device *adev = in->dev;
1861
Mingming Yin2664a5b2015-09-03 10:53:11 -07001862 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1863 if (get_usecase_from_list(adev, usecase) == NULL)
1864 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301865 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1866 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001867
Naresh Tanniru80659832014-06-04 18:17:56 +05301868
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05301869 if (CARD_STATUS_OFFLINE == in->card_status||
1870 CARD_STATUS_OFFLINE == adev->card_status) {
1871 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301872 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301873 goto error_config;
1874 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301875
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301876 if (audio_is_bluetooth_sco_device(in->device)) {
1877 if (!adev->bt_sco_on) {
1878 ALOGE("%s: SCO profile is not ready, return error", __func__);
1879 ret = -EIO;
1880 goto error_config;
1881 }
1882 }
1883
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001884 /* Check if source matches incall recording usecase criteria */
1885 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1886 if (ret)
1887 goto error_config;
1888 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001889 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1890
1891 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1892 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1893 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001894 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001895 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001896
Eric Laurentb23d5282013-05-14 15:27:20 -07001897 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001898 if (in->pcm_device_id < 0) {
1899 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1900 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001901 ret = -EINVAL;
1902 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001903 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001904
1905 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001907
1908 if (!uc_info) {
1909 ret = -ENOMEM;
1910 goto error_config;
1911 }
1912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001913 uc_info->id = in->usecase;
1914 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001915 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001916 uc_info->devices = in->device;
1917 uc_info->in_snd_device = SND_DEVICE_NONE;
1918 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001919
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001920 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301921 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1922 adev->perf_lock_opts,
1923 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001924 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001925
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301926 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1927 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001928
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301929 if (audio_extn_cin_attached_usecase(in->usecase)) {
1930 ret = audio_extn_cin_start_input_stream(in);
1931 if (ret)
1932 goto error_open;
1933 else
1934 goto done_open;
1935 }
1936
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001937 unsigned int flags = PCM_IN;
1938 unsigned int pcm_open_retry_count = 0;
1939
1940 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1941 flags |= PCM_MMAP | PCM_NOIRQ;
1942 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001943 } else if (in->realtime) {
1944 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001945 }
1946
1947 while (1) {
1948 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1949 flags, &in->config);
1950 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1951 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1952 if (in->pcm != NULL) {
1953 pcm_close(in->pcm);
1954 in->pcm = NULL;
1955 }
1956 if (pcm_open_retry_count-- == 0) {
1957 ret = -EIO;
1958 goto error_open;
1959 }
1960 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1961 continue;
1962 }
1963 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001964 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001965
1966 ALOGV("%s: pcm_prepare", __func__);
1967 ret = pcm_prepare(in->pcm);
1968 if (ret < 0) {
1969 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1970 pcm_close(in->pcm);
1971 in->pcm = NULL;
1972 goto error_open;
1973 }
1974
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001975 register_in_stream(in);
1976 if (in->realtime) {
1977 ret = pcm_start(in->pcm);
1978 if (ret < 0)
1979 goto error_open;
1980 }
1981
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301982done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301983 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001984 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001985
Eric Laurentc8400632013-02-14 19:04:54 -08001986 return ret;
1987
1988error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301989 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001991error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301992 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301993 /*
1994 * sleep 50ms to allow sufficient time for kernel
1995 * drivers to recover incases like SSR.
1996 */
1997 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001998 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001999
2000 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001}
2002
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002003void lock_input_stream(struct stream_in *in)
2004{
2005 pthread_mutex_lock(&in->pre_lock);
2006 pthread_mutex_lock(&in->lock);
2007 pthread_mutex_unlock(&in->pre_lock);
2008}
2009
2010void lock_output_stream(struct stream_out *out)
2011{
2012 pthread_mutex_lock(&out->pre_lock);
2013 pthread_mutex_lock(&out->lock);
2014 pthread_mutex_unlock(&out->pre_lock);
2015}
2016
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002017/* must be called with out->lock locked */
2018static int send_offload_cmd_l(struct stream_out* out, int command)
2019{
2020 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2021
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002022 if (!cmd) {
2023 ALOGE("failed to allocate mem for command 0x%x", command);
2024 return -ENOMEM;
2025 }
2026
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002027 ALOGVV("%s %d", __func__, command);
2028
2029 cmd->cmd = command;
2030 list_add_tail(&out->offload_cmd_list, &cmd->node);
2031 pthread_cond_signal(&out->offload_cond);
2032 return 0;
2033}
2034
2035/* must be called iwth out->lock locked */
2036static void stop_compressed_output_l(struct stream_out *out)
2037{
2038 out->offload_state = OFFLOAD_STATE_IDLE;
2039 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002040 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002041 if (out->compr != NULL) {
2042 compress_stop(out->compr);
2043 while (out->offload_thread_blocked) {
2044 pthread_cond_wait(&out->cond, &out->lock);
2045 }
2046 }
2047}
2048
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002049bool is_offload_usecase(audio_usecase_t uc_id)
2050{
2051 unsigned int i;
2052 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2053 if (uc_id == offload_usecases[i])
2054 return true;
2055 }
2056 return false;
2057}
2058
Dhananjay Kumarac341582017-02-23 23:42:25 +05302059static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002060{
vivek mehta446c3962015-09-14 10:57:35 -07002061 audio_usecase_t ret_uc = USECASE_INVALID;
2062 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002063 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002064 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302065 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002066 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2067 else
2068 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002069
vivek mehta446c3962015-09-14 10:57:35 -07002070 pthread_mutex_lock(&adev->lock);
2071 if (get_usecase_from_list(adev, ret_uc) != NULL)
2072 ret_uc = USECASE_INVALID;
2073 pthread_mutex_unlock(&adev->lock);
2074
2075 return ret_uc;
2076 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002077
2078 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002079 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2080 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2081 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2082 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002083 break;
2084 }
2085 }
vivek mehta446c3962015-09-14 10:57:35 -07002086
2087 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2088 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002089}
2090
2091static void free_offload_usecase(struct audio_device *adev,
2092 audio_usecase_t uc_id)
2093{
vivek mehta446c3962015-09-14 10:57:35 -07002094 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002095 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002096
2097 if (!adev->multi_offload_enable)
2098 return;
2099
2100 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2101 if (offload_usecases[offload_uc_index] == uc_id) {
2102 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002103 break;
2104 }
2105 }
2106 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2107}
2108
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002109static void *offload_thread_loop(void *context)
2110{
2111 struct stream_out *out = (struct stream_out *) context;
2112 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002113 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002114
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002115 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2116 set_sched_policy(0, SP_FOREGROUND);
2117 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2118
2119 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002120 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002121 for (;;) {
2122 struct offload_cmd *cmd = NULL;
2123 stream_callback_event_t event;
2124 bool send_callback = false;
2125
2126 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2127 __func__, list_empty(&out->offload_cmd_list),
2128 out->offload_state);
2129 if (list_empty(&out->offload_cmd_list)) {
2130 ALOGV("%s SLEEPING", __func__);
2131 pthread_cond_wait(&out->offload_cond, &out->lock);
2132 ALOGV("%s RUNNING", __func__);
2133 continue;
2134 }
2135
2136 item = list_head(&out->offload_cmd_list);
2137 cmd = node_to_item(item, struct offload_cmd, node);
2138 list_remove(item);
2139
2140 ALOGVV("%s STATE %d CMD %d out->compr %p",
2141 __func__, out->offload_state, cmd->cmd, out->compr);
2142
2143 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2144 free(cmd);
2145 break;
2146 }
2147
2148 if (out->compr == NULL) {
2149 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002150 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002151 pthread_cond_signal(&out->cond);
2152 continue;
2153 }
2154 out->offload_thread_blocked = true;
2155 pthread_mutex_unlock(&out->lock);
2156 send_callback = false;
2157 switch(cmd->cmd) {
2158 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002159 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002160 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002161 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002162 send_callback = true;
2163 event = STREAM_CBK_EVENT_WRITE_READY;
2164 break;
2165 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002166 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302167 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002168 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302169 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002170 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302171 if (ret < 0)
2172 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302173 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302174 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002175 compress_drain(out->compr);
2176 else
2177 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302178 if (ret != -ENETRESET) {
2179 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302180 pthread_mutex_lock(&out->lock);
2181 out->send_new_metadata = 1;
2182 out->send_next_track_params = true;
2183 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302184 event = STREAM_CBK_EVENT_DRAIN_READY;
2185 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2186 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302187 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002188 break;
2189 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002190 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002191 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002192 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002193 send_callback = true;
2194 event = STREAM_CBK_EVENT_DRAIN_READY;
2195 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302196 case OFFLOAD_CMD_ERROR:
2197 ALOGD("copl(%p): sending error callback to AF", out);
2198 send_callback = true;
2199 event = STREAM_CBK_EVENT_ERROR;
2200 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002201 default:
2202 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2203 break;
2204 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002205 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002206 out->offload_thread_blocked = false;
2207 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002208 if (send_callback && out->client_callback) {
2209 ALOGVV("%s: sending client_callback event %d", __func__, event);
2210 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002211 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002212 free(cmd);
2213 }
2214
2215 pthread_cond_signal(&out->cond);
2216 while (!list_empty(&out->offload_cmd_list)) {
2217 item = list_head(&out->offload_cmd_list);
2218 list_remove(item);
2219 free(node_to_item(item, struct offload_cmd, node));
2220 }
2221 pthread_mutex_unlock(&out->lock);
2222
2223 return NULL;
2224}
2225
2226static int create_offload_callback_thread(struct stream_out *out)
2227{
2228 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2229 list_init(&out->offload_cmd_list);
2230 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2231 offload_thread_loop, out);
2232 return 0;
2233}
2234
2235static int destroy_offload_callback_thread(struct stream_out *out)
2236{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002237 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002238 stop_compressed_output_l(out);
2239 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2240
2241 pthread_mutex_unlock(&out->lock);
2242 pthread_join(out->offload_thread, (void **) NULL);
2243 pthread_cond_destroy(&out->offload_cond);
2244
2245 return 0;
2246}
2247
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248static int stop_output_stream(struct stream_out *out)
2249{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302250 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002251 struct audio_usecase *uc_info;
2252 struct audio_device *adev = out->dev;
2253
Eric Laurent994a6932013-07-17 11:51:42 -07002254 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002255 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256 uc_info = get_usecase_from_list(adev, out->usecase);
2257 if (uc_info == NULL) {
2258 ALOGE("%s: Could not find the usecase (%d) in the list",
2259 __func__, out->usecase);
2260 return -EINVAL;
2261 }
2262
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002263 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302264 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002265 if (adev->visualizer_stop_output != NULL)
2266 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002267
2268 audio_extn_dts_remove_state_notifier_node(out->usecase);
2269
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002270 if (adev->offload_effects_stop_output != NULL)
2271 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2272 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002273
Eric Laurent150dbfe2013-02-27 14:31:02 -08002274 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002275 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002276
2277 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002278 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002280 list_remove(&uc_info->list);
2281 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302282 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002283 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302284 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002285 ALOGV("Disable passthrough , reset mixer to pcm");
2286 /* NO_PASSTHROUGH */
2287 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002288 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002289 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2290 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002291
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302292 /* Must be called after removing the usecase from list */
2293 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302294 audio_extn_keep_alive_start();
2295
Naresh Tanniru85819452017-05-04 18:55:45 -07002296 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
2297 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2298 if (ret < 0)
2299 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2300 }
2301
Eric Laurent994a6932013-07-17 11:51:42 -07002302 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002303 return ret;
2304}
2305
2306int start_output_stream(struct stream_out *out)
2307{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002308 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002309 struct audio_usecase *uc_info;
2310 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002311 char mixer_ctl_name[128];
2312 struct mixer_ctl *ctl = NULL;
2313 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002315 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2316 ret = -EINVAL;
2317 goto error_config;
2318 }
2319
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302320 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2321 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2322 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302323
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302324 if (CARD_STATUS_OFFLINE == out->card_status ||
2325 CARD_STATUS_OFFLINE == adev->card_status) {
2326 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302327 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302328 goto error_config;
2329 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302330
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302331 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2332 if (!audio_extn_a2dp_is_ready()) {
2333 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2334 //combo usecase just by pass a2dp
2335 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2336 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2337 } else {
2338 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2339 ret = -EAGAIN;
2340 goto error_config;
2341 }
2342 }
2343 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302344 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2345 if (!adev->bt_sco_on) {
2346 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2347 //combo usecase just by pass a2dp
2348 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
2349 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2350 } else {
2351 ALOGE("%s: SCO profile is not ready, return error", __func__);
2352 ret = -EAGAIN;
2353 goto error_config;
2354 }
2355 }
2356 }
2357
Eric Laurentb23d5282013-05-14 15:27:20 -07002358 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002359 if (out->pcm_device_id < 0) {
2360 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2361 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002362 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002363 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364 }
2365
2366 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002367
2368 if (!uc_info) {
2369 ret = -ENOMEM;
2370 goto error_config;
2371 }
2372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002373 uc_info->id = out->usecase;
2374 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002375 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002376 uc_info->devices = out->devices;
2377 uc_info->in_snd_device = SND_DEVICE_NONE;
2378 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002379 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002380
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302381 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2382 adev->perf_lock_opts,
2383 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302384
2385 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2386 audio_extn_keep_alive_stop();
2387 if (audio_extn_passthru_is_enabled() &&
2388 audio_extn_passthru_is_passthrough_stream(out)) {
2389 audio_extn_passthru_on_start(out);
2390 audio_extn_passthru_update_stream_configuration(adev, out);
2391 }
2392 }
2393
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002394 select_devices(adev, out->usecase);
2395
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002396 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2397 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002398 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002399 unsigned int flags = PCM_OUT;
2400 unsigned int pcm_open_retry_count = 0;
2401 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2402 flags |= PCM_MMAP | PCM_NOIRQ;
2403 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002404 } else if (out->realtime) {
2405 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002406 } else
2407 flags |= PCM_MONOTONIC;
2408
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002409 if ((adev->vr_audio_mode_enabled) &&
2410 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2411 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2412 "PCM_Dev %d Topology", out->pcm_device_id);
2413 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2414 if (!ctl) {
2415 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2416 __func__, mixer_ctl_name);
2417 } else {
2418 //if success use ULLPP
2419 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2420 __func__, mixer_ctl_name, out->pcm_device_id);
2421 //There is a still a possibility that some sessions
2422 // that request for FAST|RAW when 3D audio is active
2423 //can go through ULLPP. Ideally we expects apps to
2424 //listen to audio focus and stop concurrent playback
2425 //Also, we will look for mode flag (voice_in_communication)
2426 //before enabling the realtime flag.
2427 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2428 }
2429 }
2430
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002431 while (1) {
2432 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2433 flags, &out->config);
2434 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2435 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2436 if (out->pcm != NULL) {
2437 pcm_close(out->pcm);
2438 out->pcm = NULL;
2439 }
2440 if (pcm_open_retry_count-- == 0) {
2441 ret = -EIO;
2442 goto error_open;
2443 }
2444 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2445 continue;
2446 }
2447 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002448 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002449
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002450 ALOGV("%s: pcm_prepare", __func__);
2451 if (pcm_is_ready(out->pcm)) {
2452 ret = pcm_prepare(out->pcm);
2453 if (ret < 0) {
2454 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2455 pcm_close(out->pcm);
2456 out->pcm = NULL;
2457 goto error_open;
2458 }
2459 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302460 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302461 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
2462
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002463 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002464 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302465 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002466 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002467 out->compr = compress_open(adev->snd_card,
2468 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002469 COMPRESS_IN, &out->compr_config);
2470 if (out->compr && !is_compress_ready(out->compr)) {
2471 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2472 compress_close(out->compr);
2473 out->compr = NULL;
2474 ret = -EIO;
2475 goto error_open;
2476 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302477 /* compress_open sends params of the track, so reset the flag here */
2478 out->is_compr_metadata_avail = false;
2479
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002480 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002481 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002482
Fred Oh3f43e742015-03-04 18:42:34 -08002483 /* Since small bufs uses blocking writes, a write will be blocked
2484 for the default max poll time (20s) in the event of an SSR.
2485 Reduce the poll time to observe and deal with SSR faster.
2486 */
Ashish Jain5106d362016-05-11 19:23:33 +05302487 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002488 compress_set_max_poll_wait(out->compr, 1000);
2489 }
2490
Manish Dewangan69426c82017-01-30 17:35:36 +05302491 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302492 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05302493
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002494 audio_extn_dts_create_state_notifier_node(out->usecase);
2495 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2496 popcount(out->channel_mask),
2497 out->playback_started);
2498
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002499#ifdef DS1_DOLBY_DDP_ENABLED
2500 if (audio_extn_is_dolby_format(out->format))
2501 audio_extn_dolby_send_ddp_endp_params(adev);
2502#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302503 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2504 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002505 if (adev->visualizer_start_output != NULL)
2506 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2507 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302508 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002509 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002510 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002512
2513 if (ret == 0) {
2514 register_out_stream(out);
2515 if (out->realtime) {
2516 ret = pcm_start(out->pcm);
2517 if (ret < 0)
2518 goto error_open;
2519 }
2520 }
2521
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302522 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002523 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002524
Naresh Tanniru85819452017-05-04 18:55:45 -07002525 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
2526 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out);
2527 if (ret < 0)
2528 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
2529 }
2530
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002531 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002532error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302533 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002535error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302536 /*
2537 * sleep 50ms to allow sufficient time for kernel
2538 * drivers to recover incases like SSR.
2539 */
2540 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002541 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542}
2543
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544static int check_input_parameters(uint32_t sample_rate,
2545 audio_format_t format,
2546 int channel_count)
2547{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002548 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302550 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2551 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2552 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002553 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302554 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002555
2556 switch (channel_count) {
2557 case 1:
2558 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302559 case 3:
2560 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002561 case 6:
2562 break;
2563 default:
2564 ret = -EINVAL;
2565 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566
2567 switch (sample_rate) {
2568 case 8000:
2569 case 11025:
2570 case 12000:
2571 case 16000:
2572 case 22050:
2573 case 24000:
2574 case 32000:
2575 case 44100:
2576 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302577 case 96000:
2578 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579 break;
2580 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002581 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 }
2583
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002584 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585}
2586
2587static size_t get_input_buffer_size(uint32_t sample_rate,
2588 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002589 int channel_count,
2590 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591{
2592 size_t size = 0;
2593
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002594 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2595 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002597 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002598 if (is_low_latency)
2599 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302600
2601 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002603 /* make sure the size is multiple of 32 bytes
2604 * At 48 kHz mono 16-bit PCM:
2605 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2606 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2607 */
2608 size += 0x1f;
2609 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002610
2611 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612}
2613
Ashish Jain058165c2016-09-28 23:18:48 +05302614static size_t get_output_period_size(uint32_t sample_rate,
2615 audio_format_t format,
2616 int channel_count,
2617 int duration /*in millisecs*/)
2618{
2619 size_t size = 0;
2620 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2621
2622 if ((duration == 0) || (sample_rate == 0) ||
2623 (bytes_per_sample == 0) || (channel_count == 0)) {
2624 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2625 bytes_per_sample, channel_count);
2626 return -EINVAL;
2627 }
2628
2629 size = (sample_rate *
2630 duration *
2631 bytes_per_sample *
2632 channel_count) / 1000;
2633 /*
2634 * To have same PCM samples for all channels, the buffer size requires to
2635 * be multiple of (number of channels * bytes per sample)
2636 * For writes to succeed, the buffer must be written at address which is multiple of 32
2637 */
2638 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2639
2640 return (size/(channel_count * bytes_per_sample));
2641}
2642
Ashish Jain5106d362016-05-11 19:23:33 +05302643static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2644{
2645 uint64_t actual_frames_rendered = 0;
2646 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2647
2648 /* This adjustment accounts for buffering after app processor.
2649 * It is based on estimated DSP latency per use case, rather than exact.
2650 */
2651 int64_t platform_latency = platform_render_latency(out->usecase) *
2652 out->sample_rate / 1000000LL;
2653
2654 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2655 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2656 * hence only estimate.
2657 */
2658 int64_t signed_frames = out->written - kernel_buffer_size;
2659
2660 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2661
2662 if (signed_frames > 0)
2663 actual_frames_rendered = signed_frames;
2664
2665 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2666 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2667 (long long int)out->written, (int)kernel_buffer_size,
2668 audio_bytes_per_sample(out->compr_config.codec->format),
2669 popcount(out->channel_mask));
2670
2671 return actual_frames_rendered;
2672}
2673
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2675{
2676 struct stream_out *out = (struct stream_out *)stream;
2677
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002678 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679}
2680
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002681static int out_set_sample_rate(struct audio_stream *stream __unused,
2682 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683{
2684 return -ENOSYS;
2685}
2686
2687static size_t out_get_buffer_size(const struct audio_stream *stream)
2688{
2689 struct stream_out *out = (struct stream_out *)stream;
2690
Naresh Tanniruee3499a2017-01-05 14:05:35 +05302691 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2692 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
2693 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
2694 else
2695 return out->compr_config.fragment_size;
2696 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002697 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05302698 else if (is_offload_usecase(out->usecase) &&
2699 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302700 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002701
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002702 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002703 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704}
2705
2706static uint32_t out_get_channels(const struct audio_stream *stream)
2707{
2708 struct stream_out *out = (struct stream_out *)stream;
2709
2710 return out->channel_mask;
2711}
2712
2713static audio_format_t out_get_format(const struct audio_stream *stream)
2714{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002715 struct stream_out *out = (struct stream_out *)stream;
2716
2717 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718}
2719
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002720static int out_set_format(struct audio_stream *stream __unused,
2721 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722{
2723 return -ENOSYS;
2724}
2725
2726static int out_standby(struct audio_stream *stream)
2727{
2728 struct stream_out *out = (struct stream_out *)stream;
2729 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002730
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302731 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2732 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002734 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002736 if (adev->adm_deregister_stream)
2737 adev->adm_deregister_stream(adev->adm_data, out->handle);
2738
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002739 if (is_offload_usecase(out->usecase))
2740 stop_compressed_output_l(out);
2741
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002742 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002744 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2745 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302746 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08002747 pthread_mutex_unlock(&adev->lock);
2748 pthread_mutex_unlock(&out->lock);
2749 ALOGD("VOIP output entered standby");
2750 return 0;
2751 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002752 if (out->pcm) {
2753 pcm_close(out->pcm);
2754 out->pcm = NULL;
2755 }
2756 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002757 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302758 out->send_next_track_params = false;
2759 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002760 out->gapless_mdata.encoder_delay = 0;
2761 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002762 if (out->compr != NULL) {
2763 compress_close(out->compr);
2764 out->compr = NULL;
2765 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002766 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002768 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769 }
2770 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302771 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772 return 0;
2773}
2774
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302775static int out_on_error(struct audio_stream *stream)
2776{
2777 struct stream_out *out = (struct stream_out *)stream;
2778 bool do_standby = false;
2779
2780 lock_output_stream(out);
2781 if (!out->standby) {
2782 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2783 stop_compressed_output_l(out);
2784 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2785 } else
2786 do_standby = true;
2787 }
2788 pthread_mutex_unlock(&out->lock);
2789
2790 if (do_standby)
2791 return out_standby(&out->stream.common);
2792
2793 return 0;
2794}
2795
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302796/*
2797 *standby implementation without locks, assumes that the callee already
2798 *has taken adev and out lock.
2799 */
2800int out_standby_l(struct audio_stream *stream)
2801{
2802 struct stream_out *out = (struct stream_out *)stream;
2803 struct audio_device *adev = out->dev;
2804
2805 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2806 stream, out->usecase, use_case_table[out->usecase]);
2807
2808 if (!out->standby) {
2809 if (adev->adm_deregister_stream)
2810 adev->adm_deregister_stream(adev->adm_data, out->handle);
2811
2812 if (is_offload_usecase(out->usecase))
2813 stop_compressed_output_l(out);
2814
2815 out->standby = true;
2816 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2817 voice_extn_compress_voip_close_output_stream(stream);
2818 out->started = 0;
2819 ALOGD("VOIP output entered standby");
2820 return 0;
2821 } else if (!is_offload_usecase(out->usecase)) {
2822 if (out->pcm) {
2823 pcm_close(out->pcm);
2824 out->pcm = NULL;
2825 }
2826 } else {
2827 ALOGD("copl(%p):standby", out);
2828 out->send_next_track_params = false;
2829 out->is_compr_metadata_avail = false;
2830 out->gapless_mdata.encoder_delay = 0;
2831 out->gapless_mdata.encoder_padding = 0;
2832 if (out->compr != NULL) {
2833 compress_close(out->compr);
2834 out->compr = NULL;
2835 }
2836 }
2837 stop_output_stream(out);
2838 }
2839 ALOGD("%s: exit", __func__);
2840 return 0;
2841}
2842
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002843static int out_dump(const struct audio_stream *stream __unused,
2844 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002845{
2846 return 0;
2847}
2848
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002849static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2850{
2851 int ret = 0;
2852 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002853
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002854 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002855 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002856 return -EINVAL;
2857 }
2858
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302859 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002860
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002861 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2862 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302863 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002864 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002865 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2866 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302867 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002868 }
2869
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002870 ALOGV("%s new encoder delay %u and padding %u", __func__,
2871 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2872
2873 return 0;
2874}
2875
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002876static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2877{
2878 return out == adev->primary_output || out == adev->voice_tx_output;
2879}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002880
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302881// note: this call is safe only if the stream_cb is
2882// removed first in close_output_stream (as is done now).
2883static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2884{
2885 if (!stream || !parms)
2886 return;
2887
2888 struct stream_out *out = (struct stream_out *)stream;
2889 struct audio_device *adev = out->dev;
2890
2891 card_status_t status;
2892 int card;
2893 if (parse_snd_card_status(parms, &card, &status) < 0)
2894 return;
2895
2896 pthread_mutex_lock(&adev->lock);
2897 bool valid_cb = (card == adev->snd_card);
2898 pthread_mutex_unlock(&adev->lock);
2899
2900 if (!valid_cb)
2901 return;
2902
2903 lock_output_stream(out);
2904 if (out->card_status != status)
2905 out->card_status = status;
2906 pthread_mutex_unlock(&out->lock);
2907
2908 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
2909 use_case_table[out->usecase],
2910 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2911
2912 if (status == CARD_STATUS_OFFLINE)
2913 out_on_error(stream);
2914
2915 return;
2916}
2917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002918static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2919{
2920 struct stream_out *out = (struct stream_out *)stream;
2921 struct audio_device *adev = out->dev;
2922 struct str_parms *parms;
2923 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002924 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002925
sangwoobc677242013-08-08 16:53:43 +09002926 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002927 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002928 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302929 if (!parms)
2930 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002931 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2932 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002933 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002934 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002935 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002936
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002937 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002938 * When HDMI cable is unplugged the music playback is paused and
2939 * the policy manager sends routing=0. But the audioflinger continues
2940 * to write data until standby time (3sec). As the HDMI core is
2941 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002942 * Avoid this by routing audio to speaker until standby.
2943 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002944 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2945 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302946 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002947 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2948 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002949 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302950 /*
2951 * When A2DP is disconnected the
2952 * music playback is paused and the policy manager sends routing=0
2953 * But the audioflingercontinues to write data until standby time
2954 * (3sec). As BT is turned off, the write gets blocked.
2955 * Avoid this by routing audio to speaker until standby.
2956 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002957 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302958 (val == AUDIO_DEVICE_NONE)) {
2959 val = AUDIO_DEVICE_OUT_SPEAKER;
2960 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302961 /* To avoid a2dp to sco overlapping / BT device improper state
2962 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302963 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302964 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2965 if (!audio_extn_a2dp_is_ready()) {
2966 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2967 //combo usecase just by pass a2dp
2968 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2969 val = AUDIO_DEVICE_OUT_SPEAKER;
2970 } else {
2971 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2972 /* update device to a2dp and don't route as BT returned error
2973 * However it is still possible a2dp routing called because
2974 * of current active device disconnection (like wired headset)
2975 */
2976 out->devices = val;
2977 pthread_mutex_unlock(&out->lock);
2978 pthread_mutex_unlock(&adev->lock);
2979 goto error;
2980 }
2981 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302982 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002983 /*
2984 * select_devices() call below switches all the usecases on the same
2985 * backend to the new device. Refer to check_usecases_codec_backend() in
2986 * the select_devices(). But how do we undo this?
2987 *
2988 * For example, music playback is active on headset (deep-buffer usecase)
2989 * and if we go to ringtones and select a ringtone, low-latency usecase
2990 * will be started on headset+speaker. As we can't enable headset+speaker
2991 * and headset devices at the same time, select_devices() switches the music
2992 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2993 * So when the ringtone playback is completed, how do we undo the same?
2994 *
2995 * We are relying on the out_set_parameters() call on deep-buffer output,
2996 * once the ringtone playback is ended.
2997 * NOTE: We should not check if the current devices are same as new devices.
2998 * Because select_devices() must be called to switch back the music
2999 * playback to headset.
3000 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003001 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003002 audio_devices_t new_dev = val;
3003 bool same_dev = out->devices == new_dev;
3004 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003005
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003006 if (output_drives_call(adev, out)) {
3007 if(!voice_is_in_call(adev)) {
3008 if (adev->mode == AUDIO_MODE_IN_CALL) {
3009 adev->current_call_output = out;
3010 ret = voice_start_call(adev);
3011 }
3012 } else {
3013 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003014 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003015 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003016 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003017
3018 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003019 if (!same_dev) {
3020 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303021 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3022 adev->perf_lock_opts,
3023 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003024 if (adev->adm_on_routing_change)
3025 adev->adm_on_routing_change(adev->adm_data,
3026 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003027 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003028 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05303029 if (!same_dev)
3030 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003031 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003032 }
3033
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003035 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003037
3038 if (out == adev->primary_output) {
3039 pthread_mutex_lock(&adev->lock);
3040 audio_extn_set_parameters(adev, parms);
3041 pthread_mutex_unlock(&adev->lock);
3042 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003043 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003044 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003045 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003046
3047 audio_extn_dts_create_state_notifier_node(out->usecase);
3048 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3049 popcount(out->channel_mask),
3050 out->playback_started);
3051
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003052 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003053 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003054
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303055 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3056 if (err >= 0) {
3057 strlcpy(out->profile, value, sizeof(out->profile));
3058 ALOGV("updating stream profile with value '%s'", out->profile);
3059 lock_output_stream(out);
3060 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3061 &adev->streams_output_cfg_list,
3062 out->devices, out->flags, out->format,
3063 out->sample_rate, out->bit_width,
3064 out->channel_mask, out->profile,
3065 &out->app_type_cfg);
3066 pthread_mutex_unlock(&out->lock);
3067 }
3068
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303070error:
Eric Laurent994a6932013-07-17 11:51:42 -07003071 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003072 return ret;
3073}
3074
3075static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3076{
3077 struct stream_out *out = (struct stream_out *)stream;
3078 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003079 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080 char value[256];
3081 struct str_parms *reply = str_parms_create();
3082 size_t i, j;
3083 int ret;
3084 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003085
3086 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003087 if (reply) {
3088 str_parms_destroy(reply);
3089 }
3090 if (query) {
3091 str_parms_destroy(query);
3092 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003093 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
3094 return NULL;
3095 }
3096
Eric Laurent994a6932013-07-17 11:51:42 -07003097 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
3099 if (ret >= 0) {
3100 value[0] = '\0';
3101 i = 0;
3102 while (out->supported_channel_masks[i] != 0) {
3103 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
3104 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
3105 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003106 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003108 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109 first = false;
3110 break;
3111 }
3112 }
3113 i++;
3114 }
3115 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3116 str = str_parms_to_str(reply);
3117 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003118 voice_extn_out_get_parameters(out, query, reply);
3119 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003121
Alexy Joseph62142aa2015-11-16 15:10:34 -08003122
3123 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
3124 if (ret >= 0) {
3125 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05303126 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
3127 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08003128 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303129 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003130 } else {
3131 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05303132 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003133 }
3134 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003135 if (str)
3136 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08003137 str = str_parms_to_str(reply);
3138 }
3139
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003140 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
3141 if (ret >= 0) {
3142 value[0] = '\0';
3143 i = 0;
3144 first = true;
3145 while (out->supported_formats[i] != 0) {
3146 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
3147 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
3148 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003149 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003150 }
3151 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
3152 first = false;
3153 break;
3154 }
3155 }
3156 i++;
3157 }
3158 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003159 if (str)
3160 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003161 str = str_parms_to_str(reply);
3162 }
Mingming Yin3a941d42016-02-17 18:08:05 -08003163
3164 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
3165 if (ret >= 0) {
3166 value[0] = '\0';
3167 i = 0;
3168 first = true;
3169 while (out->supported_sample_rates[i] != 0) {
3170 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
3171 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
3172 if (!first) {
3173 strlcat(value, "|", sizeof(value));
3174 }
3175 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
3176 first = false;
3177 break;
3178 }
3179 }
3180 i++;
3181 }
3182 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
3183 if (str)
3184 free(str);
3185 str = str_parms_to_str(reply);
3186 }
3187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003188 str_parms_destroy(query);
3189 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003190 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191 return str;
3192}
3193
3194static uint32_t out_get_latency(const struct audio_stream_out *stream)
3195{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003196 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08003198 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199
Alexy Josephaa54c872014-12-03 02:46:47 -08003200 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05303201 lock_output_stream(out);
3202 latency = audio_extn_utils_compress_get_dsp_latency(out);
3203 pthread_mutex_unlock(&out->lock);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003204 } else if (out->realtime) {
3205 // since the buffer won't be filled up faster than realtime,
3206 // return a smaller number
3207 if (out->config.rate)
3208 period_ms = (out->af_period_multiplier * out->config.period_size *
3209 1000) / (out->config.rate);
3210 else
3211 period_ms = 0;
3212 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003213 } else {
3214 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003215 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003216 }
3217
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003218 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
3219 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3220 latency += audio_extn_a2dp_get_encoder_latency();
3221
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303222 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003223 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003224}
3225
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303226static float AmpToDb(float amplification)
3227{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303228 float db = DSD_VOLUME_MIN_DB;
3229 if (amplification > 0) {
3230 db = 20 * log10(amplification);
3231 if(db < DSD_VOLUME_MIN_DB)
3232 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303233 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303234 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303235}
3236
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237static int out_set_volume(struct audio_stream_out *stream, float left,
3238 float right)
3239{
Eric Laurenta9024de2013-04-04 09:19:12 -07003240 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003241 int volume[2];
3242
Eric Laurenta9024de2013-04-04 09:19:12 -07003243 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3244 /* only take left channel into account: the API is for stereo anyway */
3245 out->muted = (left == 0.0f);
3246 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003247 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303248 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003249 /*
3250 * Set mute or umute on HDMI passthrough stream.
3251 * Only take left channel into account.
3252 * Mute is 0 and unmute 1
3253 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303254 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303255 } else if (out->format == AUDIO_FORMAT_DSD){
3256 char mixer_ctl_name[128] = "DSD Volume";
3257 struct audio_device *adev = out->dev;
3258 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3259
3260 if (!ctl) {
3261 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3262 __func__, mixer_ctl_name);
3263 return -EINVAL;
3264 }
3265 volume[0] = (int)(AmpToDb(left));
3266 volume[1] = (int)(AmpToDb(right));
3267 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3268 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003269 } else {
3270 char mixer_ctl_name[128];
3271 struct audio_device *adev = out->dev;
3272 struct mixer_ctl *ctl;
3273 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003274 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003275
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003276 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3277 "Compress Playback %d Volume", pcm_device_id);
3278 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3279 if (!ctl) {
3280 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3281 __func__, mixer_ctl_name);
3282 return -EINVAL;
3283 }
3284 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3285 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3286 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3287 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003288 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003289 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003291 return -ENOSYS;
3292}
3293
3294static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3295 size_t bytes)
3296{
3297 struct stream_out *out = (struct stream_out *)stream;
3298 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003299 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003301 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303302
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303303 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003304
Dhananjay Kumarac341582017-02-23 23:42:25 +05303305 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303306 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303307 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3308 pthread_mutex_unlock(&out->lock);
3309 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303310 } else {
3311 /* increase written size during SSR to avoid mismatch
3312 * with the written frames count in AF
3313 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003314 // bytes per frame
3315 size_t bpf = audio_bytes_per_sample(out->format) *
3316 audio_channel_count_from_out_mask(out->channel_mask);
3317 if (bpf != 0)
3318 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303319 ALOGD(" %s: sound card is not active/SSR state", __func__);
3320 ret= -EIO;
3321 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303322 }
3323 }
3324
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303325 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303326 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3327 if (audio_bytes_per_sample(out->format) != 0)
3328 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3329 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303330 goto exit;
3331 }
3332
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003334 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003335 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003336 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3337 ret = voice_extn_compress_voip_start_output_stream(out);
3338 else
3339 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003340 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003341 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003342 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003343 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344 goto exit;
3345 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303346 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003347 if (last_known_cal_step != -1) {
3348 ALOGD("%s: retry previous failed cal level set", __func__);
3349 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05303350 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003351 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353
Ashish Jain81eb2a82015-05-13 10:52:34 +05303354 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003355 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303356 adev->is_channel_status_set = true;
3357 }
3358
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003359 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003360 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003361 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003362 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003363 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3364 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303365 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3366 ALOGD("copl(%p):send next track params in gapless", out);
3367 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3368 out->send_next_track_params = false;
3369 out->is_compr_metadata_avail = false;
3370 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003371 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303372 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303373 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003374
Ashish Jain83a6cc22016-06-28 14:34:17 +05303375 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303376 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303377 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303378 pthread_mutex_unlock(&out->lock);
3379 return -EINVAL;
3380 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303381 audio_format_t dst_format = out->hal_op_format;
3382 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303383
3384 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3385 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3386
Ashish Jain83a6cc22016-06-28 14:34:17 +05303387 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303388 dst_format,
3389 buffer,
3390 src_format,
3391 frames);
3392
Ashish Jain83a6cc22016-06-28 14:34:17 +05303393 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303394 bytes_to_write);
3395
3396 /*Convert written bytes in audio flinger format*/
3397 if (ret > 0)
3398 ret = ((ret * format_to_bitwidth_table[out->format]) /
3399 format_to_bitwidth_table[dst_format]);
3400 }
3401 } else
3402 ret = compress_write(out->compr, buffer, bytes);
3403
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303404 if (ret < 0)
3405 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303406 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303407 /*msg to cb thread only if non blocking write is enabled*/
3408 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303409 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003410 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303411 } else if (-ENETRESET == ret) {
3412 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303413 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05303414 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303415 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003416 }
Ashish Jain5106d362016-05-11 19:23:33 +05303417 if ( ret == (ssize_t)bytes && !out->non_blocking)
3418 out->written += bytes;
3419
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303420 /* Call compr start only when non-zero bytes of data is there to be rendered */
3421 if (!out->playback_started && ret > 0) {
3422 int status = compress_start(out->compr);
3423 if (status < 0) {
3424 ret = status;
3425 ALOGE("%s: compr start failed with err %d", __func__, errno);
3426 goto exit;
3427 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003428 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003429 out->playback_started = 1;
3430 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003431
3432 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3433 popcount(out->channel_mask),
3434 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003435 }
3436 pthread_mutex_unlock(&out->lock);
3437 return ret;
3438 } else {
3439 if (out->pcm) {
3440 if (out->muted)
3441 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003442
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303443 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003444
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003445 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003446
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003447 if (out->config.rate)
3448 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3449 out->config.rate;
3450
3451 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3452
3453 request_out_focus(out, ns);
3454
3455 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003456 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003457 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303458 out->convert_buffer != NULL) {
3459
3460 memcpy_by_audio_format(out->convert_buffer,
3461 out->hal_op_format,
3462 buffer,
3463 out->hal_ip_format,
3464 out->config.period_size * out->config.channels);
3465
3466 ret = pcm_write(out->pcm, out->convert_buffer,
3467 (out->config.period_size *
3468 out->config.channels *
3469 format_to_bitwidth_table[out->hal_op_format]));
3470 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05303471 /*
3472 * To avoid underrun in DSP when the application is not pumping
3473 * data at required rate, check for the no. of bytes and ignore
3474 * pcm_write if it is less than actual buffer size.
3475 * It is a work around to a change in compress VOIP driver.
3476 */
3477 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
3478 bytes < (out->config.period_size * out->config.channels *
3479 audio_bytes_per_sample(out->format))) {
3480 size_t voip_buf_size =
3481 out->config.period_size * out->config.channels *
3482 audio_bytes_per_sample(out->format);
3483 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
3484 __func__, bytes, voip_buf_size);
3485 usleep(((uint64_t)voip_buf_size - bytes) *
3486 1000000 / audio_stream_out_frame_size(stream) /
3487 out_get_sample_rate(&out->stream.common));
3488 ret = 0;
3489 } else
3490 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303491 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003492
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003493 release_out_focus(out);
3494
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303495 if (ret < 0)
3496 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303497 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3498 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3499 else
3500 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003501 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502 }
3503
3504exit:
Naresh Tanniru4c630392014-05-12 01:05:52 +05303505 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303506 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303507 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508 pthread_mutex_unlock(&out->lock);
3509
3510 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003511 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003512 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303513 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303514 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303515 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303516 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303517 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303518 out->standby = true;
3519 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303520 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303521 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3522 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3523 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524 }
3525 return bytes;
3526}
3527
3528static int out_get_render_position(const struct audio_stream_out *stream,
3529 uint32_t *dsp_frames)
3530{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003531 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08003532
3533 if (dsp_frames == NULL)
3534 return -EINVAL;
3535
3536 *dsp_frames = 0;
3537 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003538 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303539
3540 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3541 * this operation and adev_close_output_stream(where out gets reset).
3542 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303543 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303544 *dsp_frames = get_actual_pcm_frames_rendered(out);
3545 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3546 return 0;
3547 }
3548
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003549 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303550 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303551 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003552 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303553 if (ret < 0)
3554 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003555 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303556 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003557 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303558 if (-ENETRESET == ret) {
3559 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303560 out->card_status = CARD_STATUS_OFFLINE;
3561 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303562 } else if(ret < 0) {
3563 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303564 ret = -EINVAL;
3565 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303566 /*
3567 * Handle corner case where compress session is closed during SSR
3568 * and timestamp is queried
3569 */
3570 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303571 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303572 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303573 ret = 0;
Naresh Tanniru80659832014-06-04 18:17:56 +05303574 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303575 pthread_mutex_unlock(&out->lock);
3576 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08003577 } else if (audio_is_linear_pcm(out->format)) {
3578 *dsp_frames = out->written;
3579 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003580 } else
3581 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582}
3583
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003584static int out_add_audio_effect(const struct audio_stream *stream __unused,
3585 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586{
3587 return 0;
3588}
3589
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003590static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3591 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003592{
3593 return 0;
3594}
3595
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003596static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3597 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003598{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303599 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600}
3601
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003602static int out_get_presentation_position(const struct audio_stream_out *stream,
3603 uint64_t *frames, struct timespec *timestamp)
3604{
3605 struct stream_out *out = (struct stream_out *)stream;
3606 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003607 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003608
Ashish Jain5106d362016-05-11 19:23:33 +05303609 /* below piece of code is not guarded against any lock because audioFliner serializes
3610 * this operation and adev_close_output_stream( where out gets reset).
3611 */
3612 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303613 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303614 *frames = get_actual_pcm_frames_rendered(out);
3615 /* this is the best we can do */
3616 clock_gettime(CLOCK_MONOTONIC, timestamp);
3617 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3618 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3619 return 0;
3620 }
3621
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003622 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003623
Ashish Jain5106d362016-05-11 19:23:33 +05303624 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3625 ret = compress_get_tstamp(out->compr, &dsp_frames,
3626 &out->sample_rate);
3627 ALOGVV("%s rendered frames %ld sample_rate %d",
3628 __func__, dsp_frames, out->sample_rate);
3629 *frames = dsp_frames;
3630 if (ret < 0)
3631 ret = -errno;
3632 if (-ENETRESET == ret) {
3633 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303634 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05303635 ret = -EINVAL;
3636 } else
3637 ret = 0;
3638 /* this is the best we can do */
3639 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003640 } else {
3641 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003642 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003643 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3644 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003645 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003646 // This adjustment accounts for buffering after app processor.
3647 // It is based on estimated DSP latency per use case, rather than exact.
3648 signed_frames -=
3649 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3650
Eric Laurent949a0892013-09-20 09:20:13 -07003651 // It would be unusual for this value to be negative, but check just in case ...
3652 if (signed_frames >= 0) {
3653 *frames = signed_frames;
3654 ret = 0;
3655 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003656 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303657 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303658 *frames = out->written;
3659 clock_gettime(CLOCK_MONOTONIC, timestamp);
3660 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003661 }
3662 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003663 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003664 return ret;
3665}
3666
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003667static int out_set_callback(struct audio_stream_out *stream,
3668 stream_callback_t callback, void *cookie)
3669{
3670 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003671 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003672
3673 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003674 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003675 out->client_callback = callback;
3676 out->client_cookie = cookie;
3677 if (out->adsp_hdlr_stream_handle) {
3678 ret = audio_extn_adsp_hdlr_stream_set_callback(
3679 out->adsp_hdlr_stream_handle,
3680 callback,
3681 cookie);
3682 if (ret)
3683 ALOGW("%s:adsp hdlr callback registration failed %d",
3684 __func__, ret);
3685 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003686 pthread_mutex_unlock(&out->lock);
3687 return 0;
3688}
3689
3690static int out_pause(struct audio_stream_out* stream)
3691{
3692 struct stream_out *out = (struct stream_out *)stream;
3693 int status = -ENOSYS;
3694 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003695 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003696 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003697 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003698 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303699 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05303700 status = compress_pause(out->compr);
3701
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003702 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003703
Mingming Yin21854652016-04-13 11:54:02 -07003704 if (audio_extn_passthru_is_active()) {
3705 ALOGV("offload use case, pause passthru");
3706 audio_extn_passthru_on_pause(out);
3707 }
3708
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303709 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003710 audio_extn_dts_notify_playback_state(out->usecase, 0,
3711 out->sample_rate, popcount(out->channel_mask),
3712 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003713 }
3714 pthread_mutex_unlock(&out->lock);
3715 }
3716 return status;
3717}
3718
3719static int out_resume(struct audio_stream_out* stream)
3720{
3721 struct stream_out *out = (struct stream_out *)stream;
3722 int status = -ENOSYS;
3723 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003724 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003725 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003726 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003727 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003728 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303729 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303730 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003731 }
3732 if (!status) {
3733 out->offload_state = OFFLOAD_STATE_PLAYING;
3734 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303735 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003736 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3737 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003738 }
3739 pthread_mutex_unlock(&out->lock);
3740 }
3741 return status;
3742}
3743
3744static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3745{
3746 struct stream_out *out = (struct stream_out *)stream;
3747 int status = -ENOSYS;
3748 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003749 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003750 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003751 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3752 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3753 else
3754 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3755 pthread_mutex_unlock(&out->lock);
3756 }
3757 return status;
3758}
3759
3760static int out_flush(struct audio_stream_out* stream)
3761{
3762 struct stream_out *out = (struct stream_out *)stream;
3763 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003764 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003765 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003766 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003767 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3768 stop_compressed_output_l(out);
3769 out->written = 0;
3770 } else {
3771 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3772 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003773 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003774 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003775 return 0;
3776 }
3777 return -ENOSYS;
3778}
3779
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780/** audio_stream_in implementation **/
3781static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3782{
3783 struct stream_in *in = (struct stream_in *)stream;
3784
3785 return in->config.rate;
3786}
3787
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003788static int in_set_sample_rate(struct audio_stream *stream __unused,
3789 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003790{
3791 return -ENOSYS;
3792}
3793
3794static size_t in_get_buffer_size(const struct audio_stream *stream)
3795{
3796 struct stream_in *in = (struct stream_in *)stream;
3797
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003798 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3799 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003800 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3801 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303802 else if(audio_extn_cin_attached_usecase(in->usecase))
3803 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003804
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003805 return in->config.period_size * in->af_period_multiplier *
3806 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003807}
3808
3809static uint32_t in_get_channels(const struct audio_stream *stream)
3810{
3811 struct stream_in *in = (struct stream_in *)stream;
3812
3813 return in->channel_mask;
3814}
3815
3816static audio_format_t in_get_format(const struct audio_stream *stream)
3817{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003818 struct stream_in *in = (struct stream_in *)stream;
3819
3820 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821}
3822
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003823static int in_set_format(struct audio_stream *stream __unused,
3824 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003825{
3826 return -ENOSYS;
3827}
3828
3829static int in_standby(struct audio_stream *stream)
3830{
3831 struct stream_in *in = (struct stream_in *)stream;
3832 struct audio_device *adev = in->dev;
3833 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303834 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3835 stream, in->usecase, use_case_table[in->usecase]);
3836
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003837 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003838 if (!in->standby && in->is_st_session) {
3839 ALOGD("%s: sound trigger pcm stop lab", __func__);
3840 audio_extn_sound_trigger_stop_lab(in);
3841 in->standby = 1;
3842 }
3843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003844 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003845 if (adev->adm_deregister_stream)
3846 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3847
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003848 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003850 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3851 voice_extn_compress_voip_close_input_stream(stream);
3852 ALOGD("VOIP input entered standby");
3853 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303854 if (audio_extn_cin_attached_usecase(in->usecase))
3855 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003856 if (in->pcm) {
3857 pcm_close(in->pcm);
3858 in->pcm = NULL;
3859 }
3860 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003861 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003862 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003863 }
3864 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003865 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866 return status;
3867}
3868
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003869static int in_dump(const struct audio_stream *stream __unused,
3870 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871{
3872 return 0;
3873}
3874
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303875static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3876{
3877 if (!stream || !parms)
3878 return;
3879
3880 struct stream_in *in = (struct stream_in *)stream;
3881 struct audio_device *adev = in->dev;
3882
3883 card_status_t status;
3884 int card;
3885 if (parse_snd_card_status(parms, &card, &status) < 0)
3886 return;
3887
3888 pthread_mutex_lock(&adev->lock);
3889 bool valid_cb = (card == adev->snd_card);
3890 pthread_mutex_unlock(&adev->lock);
3891
3892 if (!valid_cb)
3893 return;
3894
3895 lock_input_stream(in);
3896 if (in->card_status != status)
3897 in->card_status = status;
3898 pthread_mutex_unlock(&in->lock);
3899
3900 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3901 use_case_table[in->usecase],
3902 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3903
3904 // a better solution would be to report error back to AF and let
3905 // it put the stream to standby
3906 if (status == CARD_STATUS_OFFLINE)
3907 in_standby(&in->stream.common);
3908
3909 return;
3910}
3911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3913{
3914 struct stream_in *in = (struct stream_in *)stream;
3915 struct audio_device *adev = in->dev;
3916 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003918 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003919
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303920 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003921 parms = str_parms_create_str(kvpairs);
3922
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303923 if (!parms)
3924 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003925 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003926 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003927
3928 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3929 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930 val = atoi(value);
3931 /* no audio source uses val == 0 */
3932 if ((in->source != val) && (val != 0)) {
3933 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003934 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3935 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3936 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003937 (in->config.rate == 8000 || in->config.rate == 16000 ||
3938 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003939 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003940 err = voice_extn_compress_voip_open_input_stream(in);
3941 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003942 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003943 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003944 }
3945 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946 }
3947 }
3948
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003949 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3950 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003952 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003953 in->device = val;
3954 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003955 if (!in->standby && !in->is_st_session) {
3956 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003957 if (adev->adm_on_routing_change)
3958 adev->adm_on_routing_change(adev->adm_data,
3959 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003960 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003961 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003962 }
3963 }
3964
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303965 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3966 if (err >= 0) {
3967 strlcpy(in->profile, value, sizeof(in->profile));
3968 ALOGV("updating stream profile with value '%s'", in->profile);
3969 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3970 &adev->streams_input_cfg_list,
3971 in->device, in->flags, in->format,
3972 in->sample_rate, in->bit_width,
3973 in->profile, &in->app_type_cfg);
3974 }
3975
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003976 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003977 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003978
3979 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303980error:
Eric Laurent994a6932013-07-17 11:51:42 -07003981 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982 return ret;
3983}
3984
3985static char* in_get_parameters(const struct audio_stream *stream,
3986 const char *keys)
3987{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003988 struct stream_in *in = (struct stream_in *)stream;
3989 struct str_parms *query = str_parms_create_str(keys);
3990 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003991 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003992
3993 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003994 if (reply) {
3995 str_parms_destroy(reply);
3996 }
3997 if (query) {
3998 str_parms_destroy(query);
3999 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004000 ALOGE("in_get_parameters: failed to create query or reply");
4001 return NULL;
4002 }
4003
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004004 ALOGV("%s: enter: keys - %s", __func__, keys);
4005
4006 voice_extn_in_get_parameters(in, query, reply);
4007
4008 str = str_parms_to_str(reply);
4009 str_parms_destroy(query);
4010 str_parms_destroy(reply);
4011
4012 ALOGV("%s: exit: returns - %s", __func__, str);
4013 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004014}
4015
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004016static int in_set_gain(struct audio_stream_in *stream __unused,
4017 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004018{
4019 return 0;
4020}
4021
4022static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4023 size_t bytes)
4024{
4025 struct stream_in *in = (struct stream_in *)stream;
4026 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304027 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304028 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004029
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004030 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304031
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004032 if (in->is_st_session) {
4033 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
4034 /* Read from sound trigger HAL */
4035 audio_extn_sound_trigger_read(in, buffer, bytes);
4036 pthread_mutex_unlock(&in->lock);
4037 return bytes;
4038 }
4039
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004040 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004041 pthread_mutex_lock(&adev->lock);
4042 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
4043 ret = voice_extn_compress_voip_start_input_stream(in);
4044 else
4045 ret = start_input_stream(in);
4046 pthread_mutex_unlock(&adev->lock);
4047 if (ret != 0) {
4048 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004049 }
4050 in->standby = 0;
4051 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004052
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004053 // what's the duration requested by the client?
4054 long ns = 0;
4055
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304056 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004057 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4058 in->config.rate;
4059
4060 request_in_focus(in, ns);
4061 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004062
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304063 if (audio_extn_cin_attached_usecase(in->usecase)) {
4064 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
4065 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304066 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004067 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304068 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07004069 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004070 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004071 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304072 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004073 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304074 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4075 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4076 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
4077 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304078 ret = -EINVAL;
4079 goto exit;
4080 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304081 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304082 ret = -errno;
4083 }
4084 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304085 /* bytes read is always set to bytes for non compress usecases */
4086 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087 }
4088
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004089 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004090
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004091 /*
4092 * Instead of writing zeroes here, we could trust the hardware
4093 * to always provide zeroes when muted.
4094 */
Pavan Chikkala63964842014-12-04 10:48:28 +05304095 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
4096 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004097 memset(buffer, 0, bytes);
4098
4099exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004100 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304101 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004102 pthread_mutex_unlock(&in->lock);
4103
4104 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304105 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304106 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304107 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304108 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304109 in->standby = true;
4110 }
Sharad Sangled17c9122017-03-20 15:58:52 +05304111 if (!audio_extn_cin_attached_usecase(in->usecase)) {
4112 bytes_read = bytes;
4113 memset(buffer, 0, bytes);
4114 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004115 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004116 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05304117 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05304118 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004119 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304120 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121}
4122
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004123static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004124{
4125 return 0;
4126}
4127
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004128static int add_remove_audio_effect(const struct audio_stream *stream,
4129 effect_handle_t effect,
4130 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004131{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004132 struct stream_in *in = (struct stream_in *)stream;
4133 int status = 0;
4134 effect_descriptor_t desc;
4135
4136 status = (*effect)->get_descriptor(effect, &desc);
4137 if (status != 0)
4138 return status;
4139
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004140 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004141 pthread_mutex_lock(&in->dev->lock);
4142 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4143 in->enable_aec != enable &&
4144 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4145 in->enable_aec = enable;
4146 if (!in->standby)
4147 select_devices(in->dev, in->usecase);
4148 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08004149 if (in->enable_ns != enable &&
4150 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4151 in->enable_ns = enable;
4152 if (!in->standby)
4153 select_devices(in->dev, in->usecase);
4154 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004155 pthread_mutex_unlock(&in->dev->lock);
4156 pthread_mutex_unlock(&in->lock);
4157
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004158 return 0;
4159}
4160
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004161static int in_add_audio_effect(const struct audio_stream *stream,
4162 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163{
Eric Laurent994a6932013-07-17 11:51:42 -07004164 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004165 return add_remove_audio_effect(stream, effect, true);
4166}
4167
4168static int in_remove_audio_effect(const struct audio_stream *stream,
4169 effect_handle_t effect)
4170{
Eric Laurent994a6932013-07-17 11:51:42 -07004171 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004172 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004173}
4174
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304175int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004176 audio_io_handle_t handle,
4177 audio_devices_t devices,
4178 audio_output_flags_t flags,
4179 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004180 struct audio_stream_out **stream_out,
4181 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004182{
4183 struct audio_device *adev = (struct audio_device *)dev;
4184 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304185 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004186 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004187 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004189 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004191 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4192
Mingming Yin3a941d42016-02-17 18:08:05 -08004193 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
4194 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304195 devices, flags, &out->stream);
4196
4197
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004198 if (!out) {
4199 return -ENOMEM;
4200 }
4201
Haynes Mathew George204045b2015-02-25 20:32:03 -08004202 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004203 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08004204 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004206 if (devices == AUDIO_DEVICE_NONE)
4207 devices = AUDIO_DEVICE_OUT_SPEAKER;
4208
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004209 out->flags = flags;
4210 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004211 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004212 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004213 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05304214 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004215 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07004216 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004217 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08004218 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304219 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304220 out->started = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004221
Mingming Yin3a941d42016-02-17 18:08:05 -08004222 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4223 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
4224 pthread_mutex_lock(&adev->lock);
4225 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
4226 ret = read_hdmi_sink_caps(out);
4227 pthread_mutex_unlock(&adev->lock);
4228 if (ret != 0) {
4229 if (ret == -ENOSYS) {
4230 /* ignore and go with default */
4231 ret = 0;
4232 } else {
4233 ALOGE("error reading hdmi sink caps");
4234 goto error_open;
4235 }
4236 }
4237 }
4238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004239 /* Init use case and pcm_config */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304240 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004241 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08004242 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004243 ret = voice_extn_compress_voip_open_output_stream(out);
4244 if (ret != 0) {
4245 ALOGE("%s: Compress voip output cannot be opened, error:%d",
4246 __func__, ret);
4247 goto error_open;
4248 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004249 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304250 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304251 pthread_mutex_lock(&adev->lock);
4252 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4253 pthread_mutex_unlock(&adev->lock);
4254
4255 // reject offload during card offline to allow
4256 // fallback to s/w paths
4257 if (offline) {
4258 ret = -ENODEV;
4259 goto error_open;
4260 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004261
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004262 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4263 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4264 ALOGE("%s: Unsupported Offload information", __func__);
4265 ret = -EINVAL;
4266 goto error_open;
4267 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004268
Mingming Yin3a941d42016-02-17 18:08:05 -08004269 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004270 if(config->offload_info.format == 0)
4271 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004272 if (config->offload_info.sample_rate == 0)
4273 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004274 }
4275
Mingming Yin90310102013-11-13 16:57:00 -08004276 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304277 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004278 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004279 ret = -EINVAL;
4280 goto error_open;
4281 }
4282
4283 out->compr_config.codec = (struct snd_codec *)
4284 calloc(1, sizeof(struct snd_codec));
4285
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004286 if (!out->compr_config.codec) {
4287 ret = -ENOMEM;
4288 goto error_open;
4289 }
4290
Dhananjay Kumarac341582017-02-23 23:42:25 +05304291 out->stream.pause = out_pause;
4292 out->stream.resume = out_resume;
4293 out->stream.flush = out_flush;
4294 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004295 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004296 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304297 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004298 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304299 } else {
4300 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4301 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004302 }
vivek mehta446c3962015-09-14 10:57:35 -07004303
4304 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004305 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4306 config->format == 0 && config->sample_rate == 0 &&
4307 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004308 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004309 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4310 } else {
4311 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4312 ret = -EEXIST;
4313 goto error_open;
4314 }
vivek mehta446c3962015-09-14 10:57:35 -07004315 }
4316
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004317 if (config->offload_info.channel_mask)
4318 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004319 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004320 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004321 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004322 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304323 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004324 ret = -EINVAL;
4325 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004326 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004327
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004328 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004329 out->sample_rate = config->offload_info.sample_rate;
4330
Mingming Yin3ee55c62014-08-04 14:23:35 -07004331 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004332
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304333 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4334 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4335 audio_extn_dolby_send_ddp_endp_params(adev);
4336 audio_extn_dolby_set_dmid(adev);
4337 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004338
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004339 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004340 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004341 out->compr_config.codec->bit_rate =
4342 config->offload_info.bit_rate;
4343 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304344 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004345 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304346 /* Update bit width only for non passthrough usecases.
4347 * For passthrough usecases, the output will always be opened @16 bit
4348 */
4349 if (!audio_extn_passthru_is_passthrough_stream(out))
4350 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304351
4352 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4353 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
4354 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
4355
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004356 /*TODO: Do we need to change it for passthrough */
4357 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004358
Manish Dewangana6fc5442015-08-24 20:30:31 +05304359 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4360 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304361 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304362 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304363 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4364 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304365
4366 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4367 AUDIO_FORMAT_PCM) {
4368
4369 /*Based on platform support, configure appropriate alsa format for corresponding
4370 *hal input format.
4371 */
4372 out->compr_config.codec->format = hal_format_to_alsa(
4373 config->offload_info.format);
4374
Ashish Jain83a6cc22016-06-28 14:34:17 +05304375 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304376 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304377 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304378
Dhananjay Kumarac341582017-02-23 23:42:25 +05304379 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304380 *hal input format and alsa format might differ based on platform support.
4381 */
4382 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304383 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304384
4385 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4386
4387 /* Check if alsa session is configured with the same format as HAL input format,
4388 * if not then derive correct fragment size needed to accomodate the
4389 * conversion of HAL input format to alsa format.
4390 */
4391 audio_extn_utils_update_direct_pcm_fragment_size(out);
4392
4393 /*if hal input and output fragment size is different this indicates HAL input format is
4394 *not same as the alsa format
4395 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304396 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304397 /*Allocate a buffer to convert input data to the alsa configured format.
4398 *size of convert buffer is equal to the size required to hold one fragment size
4399 *worth of pcm data, this is because flinger does not write more than fragment_size
4400 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304401 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4402 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304403 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4404 ret = -ENOMEM;
4405 goto error_open;
4406 }
4407 }
4408 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4409 out->compr_config.fragment_size =
4410 audio_extn_passthru_get_buffer_size(&config->offload_info);
4411 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4412 } else {
4413 out->compr_config.fragment_size =
4414 platform_get_compress_offload_buffer_size(&config->offload_info);
4415 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4416 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004417
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304418 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4419 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
4420 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07004421 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304422 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004423
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304424 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4425 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4426 }
4427
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004428 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4429 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004430
Manish Dewangan69426c82017-01-30 17:35:36 +05304431 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
4432 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
4433 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
4434 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4435 out->render_mode = RENDER_MODE_AUDIO_MASTER;
4436 } else {
4437 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
4438 }
Alexy Josephaa54c872014-12-03 02:46:47 -08004439
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05304440 memset(&out->channel_map_param, 0,
4441 sizeof(struct audio_out_channel_map_param));
4442
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004443 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304444 out->send_next_track_params = false;
4445 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004446 out->offload_state = OFFLOAD_STATE_IDLE;
4447 out->playback_started = 0;
4448
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004449 audio_extn_dts_create_state_notifier_node(out->usecase);
4450
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004451 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4452 __func__, config->offload_info.version,
4453 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304454
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304455 /* Check if DSD audio format is supported in codec
4456 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304457 */
4458
4459 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304460 (!platform_check_codec_dsd_support(adev->platform) ||
4461 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304462 ret = -EINVAL;
4463 goto error_open;
4464 }
4465
Ashish Jain5106d362016-05-11 19:23:33 +05304466 /* Disable gapless if any of the following is true
4467 * passthrough playback
4468 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304469 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304470 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304471 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304472 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07004473 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304474 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304475 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304476 check_and_set_gapless_mode(adev, false);
4477 } else
4478 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004479
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304480 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004481 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4482 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304483 if (config->format == AUDIO_FORMAT_DSD) {
4484 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4485 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4486 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004487
4488 create_offload_callback_thread(out);
4489
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004490 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304491 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004492 if (ret != 0) {
4493 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4494 __func__, ret);
4495 goto error_open;
4496 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004497 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4498 if (config->sample_rate == 0)
4499 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4500 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4501 config->sample_rate != 8000) {
4502 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4503 ret = -EINVAL;
4504 goto error_open;
4505 }
4506 out->sample_rate = config->sample_rate;
4507 out->config.rate = config->sample_rate;
4508 if (config->format == AUDIO_FORMAT_DEFAULT)
4509 config->format = AUDIO_FORMAT_PCM_16_BIT;
4510 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4511 config->format = AUDIO_FORMAT_PCM_16_BIT;
4512 ret = -EINVAL;
4513 goto error_open;
4514 }
4515 out->format = config->format;
4516 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4517 out->config = pcm_config_afe_proxy_playback;
4518 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004519 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304520 unsigned int channels = 0;
4521 /*Update config params to default if not set by the caller*/
4522 if (config->sample_rate == 0)
4523 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4524 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4525 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4526 if (config->format == AUDIO_FORMAT_DEFAULT)
4527 config->format = AUDIO_FORMAT_PCM_16_BIT;
4528
4529 channels = audio_channel_count_from_out_mask(out->channel_mask);
4530
Ashish Jain83a6cc22016-06-28 14:34:17 +05304531 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4532 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004533 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4534 out->flags);
4535 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304536 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4537 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4538 out->config = pcm_config_low_latency;
4539 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4540 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4541 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304542 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4543 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4544 if (out->config.period_size <= 0) {
4545 ALOGE("Invalid configuration period size is not valid");
4546 ret = -EINVAL;
4547 goto error_open;
4548 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304549 } else {
4550 /* primary path is the default path selected if no other outputs are available/suitable */
4551 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4552 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4553 }
4554 out->hal_ip_format = format = out->format;
4555 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4556 out->hal_op_format = pcm_format_to_hal(out->config.format);
4557 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4558 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004559 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304560 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304561 if (out->hal_ip_format != out->hal_op_format) {
4562 uint32_t buffer_size = out->config.period_size *
4563 format_to_bitwidth_table[out->hal_op_format] *
4564 out->config.channels;
4565 out->convert_buffer = calloc(1, buffer_size);
4566 if (out->convert_buffer == NULL){
4567 ALOGE("Allocation failed for convert buffer for size %d",
4568 out->compr_config.fragment_size);
4569 ret = -ENOMEM;
4570 goto error_open;
4571 }
4572 ALOGD("Convert buffer allocated of size %d", buffer_size);
4573 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004574 }
4575
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004576 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4577 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304578
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004579 /* TODO remove this hardcoding and check why width is zero*/
4580 if (out->bit_width == 0)
4581 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304582 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004583 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304584 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304585 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304586 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004587 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4588 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4589 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004590 if(adev->primary_output == NULL)
4591 adev->primary_output = out;
4592 else {
4593 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004594 ret = -EEXIST;
4595 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004596 }
4597 }
4598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004599 /* Check if this usecase is already existing */
4600 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004601 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4602 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004603 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004604 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004605 ret = -EEXIST;
4606 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004607 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004609 pthread_mutex_unlock(&adev->lock);
4610
4611 out->stream.common.get_sample_rate = out_get_sample_rate;
4612 out->stream.common.set_sample_rate = out_set_sample_rate;
4613 out->stream.common.get_buffer_size = out_get_buffer_size;
4614 out->stream.common.get_channels = out_get_channels;
4615 out->stream.common.get_format = out_get_format;
4616 out->stream.common.set_format = out_set_format;
4617 out->stream.common.standby = out_standby;
4618 out->stream.common.dump = out_dump;
4619 out->stream.common.set_parameters = out_set_parameters;
4620 out->stream.common.get_parameters = out_get_parameters;
4621 out->stream.common.add_audio_effect = out_add_audio_effect;
4622 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4623 out->stream.get_latency = out_get_latency;
4624 out->stream.set_volume = out_set_volume;
4625 out->stream.write = out_write;
4626 out->stream.get_render_position = out_get_render_position;
4627 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004628 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004629
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004630 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004631 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004632 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004633 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004634
4635 config->format = out->stream.common.get_format(&out->stream.common);
4636 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4637 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4638
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304639 /*
4640 By locking output stream before registering, we allow the callback
4641 to update stream's state only after stream's initial state is set to
4642 adev state.
4643 */
4644 lock_output_stream(out);
4645 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4646 pthread_mutex_lock(&adev->lock);
4647 out->card_status = adev->card_status;
4648 pthread_mutex_unlock(&adev->lock);
4649 pthread_mutex_unlock(&out->lock);
4650
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004651 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304652 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004653 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004654
4655 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4656 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4657 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004658 /* setup a channel for client <--> adsp communication for stream events */
4659 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07004660 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
4661 (audio_extn_ip_hdlr_intf_supported(config->format))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004662 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
4663 out->usecase, PCM_PLAYBACK);
4664 hdlr_stream_cfg.flags = out->flags;
4665 hdlr_stream_cfg.type = PCM_PLAYBACK;
4666 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
4667 &hdlr_stream_cfg);
4668 if (ret) {
4669 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
4670 out->adsp_hdlr_stream_handle = NULL;
4671 }
4672 }
Naresh Tanniru85819452017-05-04 18:55:45 -07004673 if (audio_extn_ip_hdlr_intf_supported(config->format)) {
4674 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL);
4675 if (ret < 0) {
4676 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
4677 out->ip_hdlr_handle = NULL;
4678 }
4679 }
Eric Laurent994a6932013-07-17 11:51:42 -07004680 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004681 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004682
4683error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304684 if (out->convert_buffer)
4685 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004686 free(out);
4687 *stream_out = NULL;
4688 ALOGD("%s: exit: ret %d", __func__, ret);
4689 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004690}
4691
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304692void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693 struct audio_stream_out *stream)
4694{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004695 struct stream_out *out = (struct stream_out *)stream;
4696 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004697 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004698
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304699 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4700
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304701 // must deregister from sndmonitor first to prevent races
4702 // between the callback and close_stream
4703 audio_extn_snd_mon_unregister_listener(out);
4704
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004705 /* close adsp hdrl session before standby */
4706 if (out->adsp_hdlr_stream_handle) {
4707 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
4708 if (ret)
4709 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
4710 out->adsp_hdlr_stream_handle = NULL;
4711 }
4712
Naresh Tanniru85819452017-05-04 18:55:45 -07004713 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
4714 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
4715 out->ip_hdlr_handle = NULL;
4716 }
4717
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004718 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304719 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004720 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304721 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304722 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004723 if(ret != 0)
4724 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4725 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004726 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004727 out_standby(&stream->common);
4728
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004729 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004730 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004731 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004732 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004733 if (out->compr_config.codec != NULL)
4734 free(out->compr_config.codec);
4735 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004736
Ashish Jain83a6cc22016-06-28 14:34:17 +05304737 if (out->convert_buffer != NULL) {
4738 free(out->convert_buffer);
4739 out->convert_buffer = NULL;
4740 }
4741
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004742 if (adev->voice_tx_output == out)
4743 adev->voice_tx_output = NULL;
4744
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304745 if (adev->primary_output == out)
4746 adev->primary_output = NULL;
4747
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004748 pthread_cond_destroy(&out->cond);
4749 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004750 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004751 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004752}
4753
4754static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4755{
4756 struct audio_device *adev = (struct audio_device *)dev;
4757 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004758 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004759 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004760 int ret;
4761 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004762
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004763 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004764 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004765
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304766 if (!parms)
4767 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304768
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304769 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
4770 if (ret >= 0) {
4771 /* When set to false, HAL should disable EC and NS */
4772 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4773 adev->bt_sco_on = true;
4774 else
4775 adev->bt_sco_on = false;
4776 }
4777
Naresh Tanniru4c630392014-05-12 01:05:52 +05304778 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004779 status = voice_set_parameters(adev, parms);
4780 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004781 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004782
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004783 status = platform_set_parameters(adev->platform, parms);
4784 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004785 goto done;
4786
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004787 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4788 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004789 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004790 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4791 adev->bluetooth_nrec = true;
4792 else
4793 adev->bluetooth_nrec = false;
4794 }
4795
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004796 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4797 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004798 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4799 adev->screen_off = false;
4800 else
4801 adev->screen_off = true;
4802 }
4803
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004804 ret = str_parms_get_int(parms, "rotation", &val);
4805 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004806 bool reverse_speakers = false;
4807 switch(val) {
4808 // FIXME: note that the code below assumes that the speakers are in the correct placement
4809 // relative to the user when the device is rotated 90deg from its default rotation. This
4810 // assumption is device-specific, not platform-specific like this code.
4811 case 270:
4812 reverse_speakers = true;
4813 break;
4814 case 0:
4815 case 90:
4816 case 180:
4817 break;
4818 default:
4819 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004820 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004821 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004822 if (status == 0) {
4823 if (adev->speaker_lr_swap != reverse_speakers) {
4824 adev->speaker_lr_swap = reverse_speakers;
4825 // only update the selected device if there is active pcm playback
4826 struct audio_usecase *usecase;
4827 struct listnode *node;
4828 list_for_each(node, &adev->usecase_list) {
4829 usecase = node_to_item(node, struct audio_usecase, list);
4830 if (usecase->type == PCM_PLAYBACK) {
4831 select_devices(adev, usecase->id);
4832 break;
4833 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004834 }
4835 }
4836 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004837 }
4838
Mingming Yin514a8bc2014-07-29 15:22:21 -07004839 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4840 if (ret >= 0) {
4841 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4842 adev->bt_wb_speech_enabled = true;
4843 else
4844 adev->bt_wb_speech_enabled = false;
4845 }
4846
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004847 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4848 if (ret >= 0) {
4849 val = atoi(value);
4850 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004851 ALOGV("cache new ext disp type and edid");
4852 ret = platform_get_ext_disp_type(adev->platform);
4853 if (ret < 0) {
4854 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004855 status = ret;
4856 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004857 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004858 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004859 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004860 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004861 /*
4862 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4863 * Per AudioPolicyManager, USB device is higher priority than WFD.
4864 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4865 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4866 * starting voice call on USB
4867 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004868 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4869 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004870 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4871 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004872 }
vivek mehta344576a2016-04-12 18:56:03 -07004873 ALOGV("detected USB connect .. disable proxy");
4874 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004875 }
4876 }
4877
4878 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4879 if (ret >= 0) {
4880 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004881 /*
4882 * The HDMI / Displayport disconnect handling has been moved to
4883 * audio extension to ensure that its parameters are not
4884 * invalidated prior to updating sysfs of the disconnect event
4885 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4886 */
4887 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004888 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004889 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4890 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304891 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4892 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004893 }
vivek mehta344576a2016-04-12 18:56:03 -07004894 ALOGV("detected USB disconnect .. enable proxy");
4895 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004896 }
4897 }
4898
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304899 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4900 if (ret >= 0) {
4901 struct audio_usecase *usecase;
4902 struct listnode *node;
4903 list_for_each(node, &adev->usecase_list) {
4904 usecase = node_to_item(node, struct audio_usecase, list);
4905 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004906 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304907 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08004908
4909 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304910 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08004911 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304912 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304913 //force device switch to re configure encoder
4914 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304915 audio_extn_a2dp_set_handoff_mode(false);
4916 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304917 break;
4918 }
4919 }
4920 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004921
4922 //handle vr audio setparam
4923 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4924 value, sizeof(value));
4925 if (ret >= 0) {
4926 ALOGI("Setting vr mode to be %s", value);
4927 if (!strncmp(value, "true", 4)) {
4928 adev->vr_audio_mode_enabled = true;
4929 ALOGI("Setting vr mode to true");
4930 } else if (!strncmp(value, "false", 5)) {
4931 adev->vr_audio_mode_enabled = false;
4932 ALOGI("Setting vr mode to false");
4933 } else {
4934 ALOGI("wrong vr mode set");
4935 }
4936 }
4937
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304938 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004939done:
4940 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004941 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304942error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004943 ALOGV("%s: exit with code(%d)", __func__, status);
4944 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004945}
4946
4947static char* adev_get_parameters(const struct audio_hw_device *dev,
4948 const char *keys)
4949{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004950 struct audio_device *adev = (struct audio_device *)dev;
4951 struct str_parms *reply = str_parms_create();
4952 struct str_parms *query = str_parms_create_str(keys);
4953 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304954 char value[256] = {0};
4955 int ret = 0;
4956
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004957 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004958 if (reply) {
4959 str_parms_destroy(reply);
4960 }
4961 if (query) {
4962 str_parms_destroy(query);
4963 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004964 ALOGE("adev_get_parameters: failed to create query or reply");
4965 return NULL;
4966 }
4967
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004968 //handle vr audio getparam
4969
4970 ret = str_parms_get_str(query,
4971 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4972 value, sizeof(value));
4973
4974 if (ret >= 0) {
4975 bool vr_audio_enabled = false;
4976 pthread_mutex_lock(&adev->lock);
4977 vr_audio_enabled = adev->vr_audio_mode_enabled;
4978 pthread_mutex_unlock(&adev->lock);
4979
4980 ALOGI("getting vr mode to %d", vr_audio_enabled);
4981
4982 if (vr_audio_enabled) {
4983 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4984 "true");
4985 goto exit;
4986 } else {
4987 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4988 "false");
4989 goto exit;
4990 }
4991 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004992
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004993 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004994 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004995 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004996 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304997 pthread_mutex_unlock(&adev->lock);
4998
Naresh Tannirud7205b62014-06-20 02:54:48 +05304999exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005000 str = str_parms_to_str(reply);
5001 str_parms_destroy(query);
5002 str_parms_destroy(reply);
5003
5004 ALOGV("%s: exit: returns - %s", __func__, str);
5005 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005006}
5007
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005008static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005009{
5010 return 0;
5011}
5012
5013static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5014{
Haynes Mathew George5191a852013-09-11 14:19:36 -07005015 int ret;
5016 struct audio_device *adev = (struct audio_device *)dev;
5017 pthread_mutex_lock(&adev->lock);
5018 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07005019 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005020 pthread_mutex_unlock(&adev->lock);
5021 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005022}
5023
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005024static int adev_set_master_volume(struct audio_hw_device *dev __unused,
5025 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005026{
5027 return -ENOSYS;
5028}
5029
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005030static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5031 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005032{
5033 return -ENOSYS;
5034}
5035
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005036static int adev_set_master_mute(struct audio_hw_device *dev __unused,
5037 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005038{
5039 return -ENOSYS;
5040}
5041
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005042static int adev_get_master_mute(struct audio_hw_device *dev __unused,
5043 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005044{
5045 return -ENOSYS;
5046}
5047
5048static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5049{
5050 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005052 pthread_mutex_lock(&adev->lock);
5053 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005054 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005055 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08005056 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005057 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07005058 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005059 adev->current_call_output = NULL;
5060 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005061 }
5062 pthread_mutex_unlock(&adev->lock);
5063 return 0;
5064}
5065
5066static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5067{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005068 int ret;
5069
5070 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08005071 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005072 ret = voice_set_mic_mute((struct audio_device *)dev, state);
5073 pthread_mutex_unlock(&adev->lock);
5074
5075 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005076}
5077
5078static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5079{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005080 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005081 return 0;
5082}
5083
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005084static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005085 const struct audio_config *config)
5086{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005087 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005088
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005089 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
5090 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005091}
5092
5093static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005094 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005095 audio_devices_t devices,
5096 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005097 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305098 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005099 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005100 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005101{
5102 struct audio_device *adev = (struct audio_device *)dev;
5103 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005104 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005105 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005106 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305107 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005109 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305110 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
5111 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005112 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305113 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005114
5115 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005116
5117 if (!in) {
5118 ALOGE("failed to allocate input stream");
5119 return -ENOMEM;
5120 }
5121
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305122 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305123 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
5124 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005125 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005126 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005127
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005128 in->stream.common.get_sample_rate = in_get_sample_rate;
5129 in->stream.common.set_sample_rate = in_set_sample_rate;
5130 in->stream.common.get_buffer_size = in_get_buffer_size;
5131 in->stream.common.get_channels = in_get_channels;
5132 in->stream.common.get_format = in_get_format;
5133 in->stream.common.set_format = in_set_format;
5134 in->stream.common.standby = in_standby;
5135 in->stream.common.dump = in_dump;
5136 in->stream.common.set_parameters = in_set_parameters;
5137 in->stream.common.get_parameters = in_get_parameters;
5138 in->stream.common.add_audio_effect = in_add_audio_effect;
5139 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5140 in->stream.set_gain = in_set_gain;
5141 in->stream.read = in_read;
5142 in->stream.get_input_frames_lost = in_get_input_frames_lost;
5143
5144 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005145 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005146 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005147 in->standby = 1;
5148 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005149 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005150 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005151
Dhananjay Kumar973fc362017-01-09 18:48:15 +05305152 in->usecase = USECASE_AUDIO_RECORD;
5153 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
5154 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
5155 is_low_latency = true;
5156#if LOW_LATENCY_CAPTURE_USE_CASE
5157 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
5158#endif
5159 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
5160 }
5161
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005162 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005163 if (in->realtime) {
5164 in->config = pcm_config_audio_capture_rt;
5165 in->sample_rate = in->config.rate;
5166 in->af_period_multiplier = af_period_multiplier;
5167 } else {
5168 in->config = pcm_config_audio_capture;
5169 in->config.rate = config->sample_rate;
5170 in->sample_rate = config->sample_rate;
5171 in->af_period_multiplier = 1;
5172 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305173 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005174
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305175 /* restrict 24 bit capture for unprocessed source only
5176 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
5177 */
5178 if (config->format == AUDIO_FORMAT_DEFAULT) {
5179 config->format = AUDIO_FORMAT_PCM_16_BIT;
5180 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
5181 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
5182 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
5183 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5184 bool ret_error = false;
5185 in->bit_width = 24;
5186 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5187 from HAL is 24_packed and 8_24
5188 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5189 24_packed return error indicating supported format is 24_packed
5190 *> In case of any other source requesting 24 bit or float return error
5191 indicating format supported is 16 bit only.
5192
5193 on error flinger will retry with supported format passed
5194 */
5195 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
5196 (source != AUDIO_SOURCE_CAMCORDER)) {
5197 config->format = AUDIO_FORMAT_PCM_16_BIT;
5198 if (config->sample_rate > 48000)
5199 config->sample_rate = 48000;
5200 ret_error = true;
5201 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
5202 in->config.format = PCM_FORMAT_S24_3LE;
5203 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5204 in->config.format = PCM_FORMAT_S24_LE;
5205 } else {
5206 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
5207 ret_error = true;
5208 }
5209
5210 if (ret_error) {
5211 ret = -EINVAL;
5212 goto err_open;
5213 }
5214 }
5215
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305216 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305217 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
5218 (adev->mode != AUDIO_MODE_IN_CALL)) {
5219 ret = -EINVAL;
5220 goto err_open;
5221 }
5222
5223 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
5224 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005225 if (config->sample_rate == 0)
5226 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5227 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5228 config->sample_rate != 8000) {
5229 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5230 ret = -EINVAL;
5231 goto err_open;
5232 }
5233 if (config->format == AUDIO_FORMAT_DEFAULT)
5234 config->format = AUDIO_FORMAT_PCM_16_BIT;
5235 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5236 config->format = AUDIO_FORMAT_PCM_16_BIT;
5237 ret = -EINVAL;
5238 goto err_open;
5239 }
5240
5241 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5242 in->config = pcm_config_afe_proxy_record;
5243 in->config.channels = channel_count;
5244 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305245 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305246 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
5247 in, config, &channel_mask_updated)) {
5248 if (channel_mask_updated == true) {
5249 ALOGD("%s: return error to retry with updated channel mask (%#x)",
5250 __func__, config->channel_mask);
5251 ret = -EINVAL;
5252 goto err_open;
5253 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05305254 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07005255 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005256 audio_extn_compr_cap_format_supported(config->format) &&
5257 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005258 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305259 } else if (audio_extn_cin_applicable_stream(in)) {
5260 ret = audio_extn_cin_configure_input_stream(in);
5261 if (ret)
5262 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005263 } else {
5264 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005265 if (!in->realtime) {
5266 in->format = config->format;
5267 frame_size = audio_stream_in_frame_size(&in->stream);
5268 buffer_size = get_input_buffer_size(config->sample_rate,
5269 config->format,
5270 channel_count,
5271 is_low_latency);
5272 in->config.period_size = buffer_size / frame_size;
5273 }
5274
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005275 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08005276 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005277 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005278 (in->config.rate == 8000 || in->config.rate == 16000 ||
5279 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005280 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5281 voice_extn_compress_voip_open_input_stream(in);
5282 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005283 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005284
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305285 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5286 &adev->streams_input_cfg_list,
5287 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305288 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305289
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005290 /* This stream could be for sound trigger lab,
5291 get sound trigger pcm if present */
5292 audio_extn_sound_trigger_check_and_get_session(in);
5293
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305294 lock_input_stream(in);
5295 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5296 pthread_mutex_lock(&adev->lock);
5297 in->card_status = adev->card_status;
5298 pthread_mutex_unlock(&adev->lock);
5299 pthread_mutex_unlock(&in->lock);
5300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005301 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005302 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005303 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005304
5305err_open:
5306 free(in);
5307 *stream_in = NULL;
5308 return ret;
5309}
5310
5311static void adev_close_input_stream(struct audio_hw_device *dev,
5312 struct audio_stream_in *stream)
5313{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005314 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005315 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005316 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305317
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305318 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005319
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305320 // must deregister from sndmonitor first to prevent races
5321 // between the callback and close_stream
5322 audio_extn_snd_mon_unregister_listener(stream);
5323
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305324 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005325 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305326
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005327 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305328 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005329 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305330 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005331 if (ret != 0)
5332 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5333 __func__, ret);
5334 } else
5335 in_standby(&stream->common);
5336
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005337 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005338 audio_extn_ssr_deinit();
5339 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005340
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305341 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005342 audio_extn_compr_cap_format_supported(in->config.format))
5343 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305344
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305345 if (audio_extn_cin_attached_usecase(in->usecase))
5346 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005347
Mingming Yinfd7607b2016-01-22 12:48:44 -08005348 if (in->is_st_session) {
5349 ALOGV("%s: sound trigger pcm stop lab", __func__);
5350 audio_extn_sound_trigger_stop_lab(in);
5351 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005352 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005353 return;
5354}
5355
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005356static int adev_dump(const audio_hw_device_t *device __unused,
5357 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005358{
5359 return 0;
5360}
5361
5362static int adev_close(hw_device_t *device)
5363{
5364 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005365
5366 if (!adev)
5367 return 0;
5368
5369 pthread_mutex_lock(&adev_init_lock);
5370
5371 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305372 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005373 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005374 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305375 audio_extn_utils_release_streams_cfg_lists(
5376 &adev->streams_output_cfg_list,
5377 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305378 if (audio_extn_qaf_is_enabled())
5379 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005380 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005381 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005382 free(adev->snd_dev_ref_cnt);
5383 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005384 if (adev->adm_deinit)
5385 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305386 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005387 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305388 audio_extn_snd_mon_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005389 free(device);
5390 adev = NULL;
5391 }
5392 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005393
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005394 return 0;
5395}
5396
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005397/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5398 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5399 * just that it _might_ work.
5400 */
5401static int period_size_is_plausible_for_low_latency(int period_size)
5402{
5403 switch (period_size) {
5404 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005405 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005406 case 240:
5407 case 320:
5408 case 480:
5409 return 1;
5410 default:
5411 return 0;
5412 }
5413}
5414
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305415static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
5416{
5417 bool is_snd_card_status = false;
5418 bool is_ext_device_status = false;
5419 char value[32];
5420 int card = -1;
5421 card_status_t status;
5422
5423 if (cookie != adev || !parms)
5424 return;
5425
5426 if (!parse_snd_card_status(parms, &card, &status)) {
5427 is_snd_card_status = true;
5428 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
5429 is_ext_device_status = true;
5430 } else {
5431 // not a valid event
5432 return;
5433 }
5434
5435 pthread_mutex_lock(&adev->lock);
5436 if (card == adev->snd_card || is_ext_device_status) {
5437 if (is_snd_card_status && adev->card_status != status) {
5438 adev->card_status = status;
5439 platform_snd_card_update(adev->platform, status);
5440 audio_extn_fm_set_parameters(adev, parms);
5441 } else if (is_ext_device_status) {
5442 platform_set_parameters(adev->platform, parms);
5443 }
5444 }
5445 pthread_mutex_unlock(&adev->lock);
5446 return;
5447}
5448
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005449static int adev_open(const hw_module_t *module, const char *name,
5450 hw_device_t **device)
5451{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305452 int ret;
5453
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005454 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005455 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5456
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005457 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005458 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005459 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005460 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005461 ALOGD("%s: returning existing instance of adev", __func__);
5462 ALOGD("%s: exit", __func__);
5463 pthread_mutex_unlock(&adev_init_lock);
5464 return 0;
5465 }
5466
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005467 adev = calloc(1, sizeof(struct audio_device));
5468
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005469 if (!adev) {
5470 pthread_mutex_unlock(&adev_init_lock);
5471 return -ENOMEM;
5472 }
5473
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005474 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5475
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05305476#ifdef DYNAMIC_LOG_ENABLED
5477 register_for_dynamic_logging("hal");
5478#endif
5479
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005480 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5481 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5482 adev->device.common.module = (struct hw_module_t *)module;
5483 adev->device.common.close = adev_close;
5484
5485 adev->device.init_check = adev_init_check;
5486 adev->device.set_voice_volume = adev_set_voice_volume;
5487 adev->device.set_master_volume = adev_set_master_volume;
5488 adev->device.get_master_volume = adev_get_master_volume;
5489 adev->device.set_master_mute = adev_set_master_mute;
5490 adev->device.get_master_mute = adev_get_master_mute;
5491 adev->device.set_mode = adev_set_mode;
5492 adev->device.set_mic_mute = adev_set_mic_mute;
5493 adev->device.get_mic_mute = adev_get_mic_mute;
5494 adev->device.set_parameters = adev_set_parameters;
5495 adev->device.get_parameters = adev_get_parameters;
5496 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5497 adev->device.open_output_stream = adev_open_output_stream;
5498 adev->device.close_output_stream = adev_close_output_stream;
5499 adev->device.open_input_stream = adev_open_input_stream;
5500 adev->device.close_input_stream = adev_close_input_stream;
5501 adev->device.dump = adev_dump;
5502
5503 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005504 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005505 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005506 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005507 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005508 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005509 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005510 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305511 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005512 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005513 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005514 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005515 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005516 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005517 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305518 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305519 adev->perf_lock_opts[0] = 0x101;
5520 adev->perf_lock_opts[1] = 0x20E;
5521 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005523 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005524 adev->platform = platform_init(adev);
5525 if (!adev->platform) {
5526 free(adev->snd_dev_ref_cnt);
5527 free(adev);
5528 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5529 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005530 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305531 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005532 return -EINVAL;
5533 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005534
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305535 if (audio_extn_qaf_is_enabled()) {
5536 ret = audio_extn_qaf_init(adev);
5537 if (ret < 0) {
5538 free(adev);
5539 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5540 *device = NULL;
5541 pthread_mutex_unlock(&adev_init_lock);
5542 pthread_mutex_destroy(&adev->lock);
5543 return ret;
5544 }
5545
5546 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5547 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5548 }
5549
Eric Laurentc4aef752013-09-12 17:45:53 -07005550 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5551 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5552 if (adev->visualizer_lib == NULL) {
5553 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5554 } else {
5555 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5556 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005557 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005558 "visualizer_hal_start_output");
5559 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005560 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005561 "visualizer_hal_stop_output");
5562 }
5563 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305564 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005565 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005566 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005567
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005568 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5569 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5570 if (adev->offload_effects_lib == NULL) {
5571 ALOGE("%s: DLOPEN failed for %s", __func__,
5572 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5573 } else {
5574 ALOGV("%s: DLOPEN successful for %s", __func__,
5575 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5576 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305577 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005578 "offload_effects_bundle_hal_start_output");
5579 adev->offload_effects_stop_output =
5580 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5581 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005582 adev->offload_effects_set_hpx_state =
5583 (int (*)(bool))dlsym(adev->offload_effects_lib,
5584 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305585 adev->offload_effects_get_parameters =
5586 (void (*)(struct str_parms *, struct str_parms *))
5587 dlsym(adev->offload_effects_lib,
5588 "offload_effects_bundle_get_parameters");
5589 adev->offload_effects_set_parameters =
5590 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5591 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005592 }
5593 }
5594
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005595 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5596 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5597 if (adev->adm_lib == NULL) {
5598 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5599 } else {
5600 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5601 adev->adm_init = (adm_init_t)
5602 dlsym(adev->adm_lib, "adm_init");
5603 adev->adm_deinit = (adm_deinit_t)
5604 dlsym(adev->adm_lib, "adm_deinit");
5605 adev->adm_register_input_stream = (adm_register_input_stream_t)
5606 dlsym(adev->adm_lib, "adm_register_input_stream");
5607 adev->adm_register_output_stream = (adm_register_output_stream_t)
5608 dlsym(adev->adm_lib, "adm_register_output_stream");
5609 adev->adm_deregister_stream = (adm_deregister_stream_t)
5610 dlsym(adev->adm_lib, "adm_deregister_stream");
5611 adev->adm_request_focus = (adm_request_focus_t)
5612 dlsym(adev->adm_lib, "adm_request_focus");
5613 adev->adm_abandon_focus = (adm_abandon_focus_t)
5614 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005615 adev->adm_set_config = (adm_set_config_t)
5616 dlsym(adev->adm_lib, "adm_set_config");
5617 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5618 dlsym(adev->adm_lib, "adm_request_focus_v2");
5619 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5620 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5621 adev->adm_on_routing_change = (adm_on_routing_change_t)
5622 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005623 }
5624 }
5625
Mingming Yin514a8bc2014-07-29 15:22:21 -07005626 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005627 //initialize this to false for now,
5628 //this will be set to true through set param
5629 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005630
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005631 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005632 *device = &adev->device.common;
5633
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305634 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5635 &adev->streams_output_cfg_list,
5636 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005637
Kiran Kandi910e1862013-10-29 13:29:42 -07005638 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005639
5640 char value[PROPERTY_VALUE_MAX];
5641 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005642 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005643 trial = atoi(value);
5644 if (period_size_is_plausible_for_low_latency(trial)) {
5645 pcm_config_low_latency.period_size = trial;
5646 pcm_config_low_latency.start_threshold = trial / 4;
5647 pcm_config_low_latency.avail_min = trial / 4;
5648 configured_low_latency_capture_period_size = trial;
5649 }
5650 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005651 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005652 trial = atoi(value);
5653 if (period_size_is_plausible_for_low_latency(trial)) {
5654 configured_low_latency_capture_period_size = trial;
5655 }
5656 }
5657
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005658 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005659 af_period_multiplier = atoi(value);
5660 if (af_period_multiplier < 0)
5661 af_period_multiplier = 2;
5662 else if (af_period_multiplier > 4)
5663 af_period_multiplier = 4;
5664
5665 ALOGV("new period_multiplier = %d", af_period_multiplier);
5666 }
5667
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005668 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005669 pthread_mutex_unlock(&adev_init_lock);
5670
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005671 if (adev->adm_init)
5672 adev->adm_data = adev->adm_init();
5673
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305674 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305675 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005676 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305677
5678 audio_extn_snd_mon_init();
5679 pthread_mutex_lock(&adev->lock);
5680 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
5681 adev->card_status = CARD_STATUS_ONLINE;
5682 pthread_mutex_unlock(&adev->lock);
5683 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
5684
Eric Laurent994a6932013-07-17 11:51:42 -07005685 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005686 return 0;
5687}
5688
5689static struct hw_module_methods_t hal_module_methods = {
5690 .open = adev_open,
5691};
5692
5693struct audio_module HAL_MODULE_INFO_SYM = {
5694 .common = {
5695 .tag = HARDWARE_MODULE_TAG,
5696 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5697 .hal_api_version = HARDWARE_HAL_API_VERSION,
5698 .id = AUDIO_HARDWARE_MODULE_ID,
5699 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005700 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005701 .methods = &hal_module_methods,
5702 },
5703};