blob: 2a4d2ed7961d1e7a64901914700e213625f9b9bd [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, 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"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700168 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
169 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700170 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700171 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700172 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
179 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700180
Eric Laurentb23d5282013-05-14 15:27:20 -0700181 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700182 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700183 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700184 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700185 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800186 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800187 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700188 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700189
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700190 [USECASE_VOICE2_CALL] = "voice2-call",
191 [USECASE_VOLTE_CALL] = "volte-call",
192 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800193 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800194 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
195 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800196 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700197 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
198 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
199 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800200 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
201 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
202 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
203
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700204 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
205 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700206 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
207 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700208
209 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
210 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700211};
212
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700213static const audio_usecase_t offload_usecases[] = {
214 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700223};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800224
225#define STRING_TO_ENUM(string) { #string, string }
226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800227struct string_to_enum {
228 const char *name;
229 uint32_t value;
230};
231
232static const struct string_to_enum out_channels_name_to_enum_table[] = {
233 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
241};
242
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700243static const struct string_to_enum out_formats_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800247 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
248 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
249};
250
251//list of all supported sample rates by HDMI specification.
252static const int out_hdmi_sample_rates[] = {
253 32000, 44100, 48000, 88200, 96000, 176400, 192000,
254};
255
256static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
257 STRING_TO_ENUM(32000),
258 STRING_TO_ENUM(44100),
259 STRING_TO_ENUM(48000),
260 STRING_TO_ENUM(88200),
261 STRING_TO_ENUM(96000),
262 STRING_TO_ENUM(176400),
263 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700264};
265
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700266static struct audio_device *adev = NULL;
267static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700268static unsigned int audio_device_ref_count;
269
vivek mehtaa76401a2015-04-24 14:12:15 -0700270__attribute__ ((visibility ("default")))
271bool audio_hw_send_gain_dep_calibration(int level) {
272 bool ret_val = false;
273 ALOGV("%s: called ... ", __func__);
274
275 pthread_mutex_lock(&adev_init_lock);
276
277 if (adev != NULL && adev->platform != NULL) {
278 pthread_mutex_lock(&adev->lock);
279 ret_val = platform_send_gain_dep_cal(adev->platform, level);
280 pthread_mutex_unlock(&adev->lock);
281 } else {
282 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
283 }
284
285 pthread_mutex_unlock(&adev_init_lock);
286
287 return ret_val;
288}
289
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800290static int check_and_set_gapless_mode(struct audio_device *adev) {
291
292
293 char value[PROPERTY_VALUE_MAX] = {0};
294 bool gapless_enabled = false;
295 const char *mixer_ctl_name = "Compress Gapless Playback";
296 struct mixer_ctl *ctl;
297
298 ALOGV("%s:", __func__);
299 property_get("audio.offload.gapless.enabled", value, NULL);
300 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
301
302 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
303 if (!ctl) {
304 ALOGE("%s: Could not get ctl for mixer cmd - %s",
305 __func__, mixer_ctl_name);
306 return -EINVAL;
307 }
308
309 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
310 ALOGE("%s: Could not set gapless mode %d",
311 __func__, gapless_enabled);
312 return -EINVAL;
313 }
314 return 0;
315}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700316
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700317static bool is_supported_format(audio_format_t format)
318{
Eric Laurent86e17132013-09-12 17:49:30 -0700319 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530320 format == AUDIO_FORMAT_AAC_LC ||
321 format == AUDIO_FORMAT_AAC_HE_V1 ||
322 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530323 format == AUDIO_FORMAT_AAC_ADTS_LC ||
324 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
325 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800326 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700327 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700328 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800329 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530330 format == AUDIO_FORMAT_ALAC ||
331 format == AUDIO_FORMAT_APE ||
332 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800333 format == AUDIO_FORMAT_WMA ||
334 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800335 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700336
337 return false;
338}
339
340static int get_snd_codec_id(audio_format_t format)
341{
342 int id = 0;
343
Ashish Jainf9b78162014-08-25 20:36:25 +0530344 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700345 case AUDIO_FORMAT_MP3:
346 id = SND_AUDIOCODEC_MP3;
347 break;
348 case AUDIO_FORMAT_AAC:
349 id = SND_AUDIOCODEC_AAC;
350 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530351 case AUDIO_FORMAT_AAC_ADTS:
352 id = SND_AUDIOCODEC_AAC;
353 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530354 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700355 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800356 id = SND_AUDIOCODEC_PCM;
357 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700358 case AUDIO_FORMAT_FLAC:
359 id = SND_AUDIOCODEC_FLAC;
360 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530361 case AUDIO_FORMAT_ALAC:
362 id = SND_AUDIOCODEC_ALAC;
363 break;
364 case AUDIO_FORMAT_APE:
365 id = SND_AUDIOCODEC_APE;
366 break;
367 case AUDIO_FORMAT_VORBIS:
368 id = SND_AUDIOCODEC_VORBIS;
369 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800370 case AUDIO_FORMAT_WMA:
371 id = SND_AUDIOCODEC_WMA;
372 break;
373 case AUDIO_FORMAT_WMA_PRO:
374 id = SND_AUDIOCODEC_WMA_PRO;
375 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700376 default:
Mingming Yin90310102013-11-13 16:57:00 -0800377 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700378 }
379
380 return id;
381}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800382
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530383int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530384{
385 int snd_scard_state;
386
387 if (!adev)
388 return SND_CARD_STATE_OFFLINE;
389
390 pthread_mutex_lock(&adev->snd_card_status.lock);
391 snd_scard_state = adev->snd_card_status.state;
392 pthread_mutex_unlock(&adev->snd_card_status.lock);
393
394 return snd_scard_state;
395}
396
397static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
398{
399 if (!adev)
400 return -ENOSYS;
401
402 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700403 if (adev->snd_card_status.state != snd_scard_state) {
404 adev->snd_card_status.state = snd_scard_state;
405 platform_snd_card_update(adev->platform, snd_scard_state);
406 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530407 pthread_mutex_unlock(&adev->snd_card_status.lock);
408
409 return 0;
410}
411
Avinash Vaish71a8b972014-07-24 15:36:33 +0530412static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
413 struct audio_usecase *uc_info)
414{
415 struct listnode *node;
416 struct audio_usecase *usecase;
417
418 if (uc_info == NULL)
419 return -EINVAL;
420
421 /* Re-route all voice usecases on the shared backend other than the
422 specified usecase to new snd devices */
423 list_for_each(node, &adev->usecase_list) {
424 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800425 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530426 enable_audio_route(adev, usecase);
427 }
428 return 0;
429}
430
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700431int pcm_ioctl(struct pcm *pcm, int request, ...)
432{
433 va_list ap;
434 void * arg;
435 int pcm_fd = *(int*)pcm;
436
437 va_start(ap, request);
438 arg = va_arg(ap, void *);
439 va_end(ap);
440
441 return ioctl(pcm_fd, request, arg);
442}
443
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700444int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700445 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800446{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700447 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700448 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800449
450 if (usecase == NULL)
451 return -EINVAL;
452
453 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
454
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800455 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700456 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800457 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700458 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800459
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800460#ifdef DS1_DOLBY_DAP_ENABLED
461 audio_extn_dolby_set_dmid(adev);
462 audio_extn_dolby_set_endpoint(adev);
463#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700464 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700465 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530466 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700467 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530468 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800469 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700470 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700471 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700472 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800473 ALOGV("%s: exit", __func__);
474 return 0;
475}
476
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700477int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700478 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800479{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700480 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700481 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800482
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530483 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800484 return -EINVAL;
485
486 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700487 if (usecase->type == PCM_CAPTURE)
488 snd_device = usecase->in_snd_device;
489 else
490 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800491 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700492 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700493 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700494 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700495 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530496 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800497 ALOGV("%s: exit", __func__);
498 return 0;
499}
500
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700501int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700502 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800503{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700504 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
505
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800506 if (snd_device < SND_DEVICE_MIN ||
507 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800508 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800509 return -EINVAL;
510 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700511
512 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700513
514 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
515 ALOGE("%s: Invalid sound device returned", __func__);
516 return -EINVAL;
517 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700518 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700519 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700520 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700521 return 0;
522 }
523
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530524
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700525 if (audio_extn_spkr_prot_is_enabled())
526 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700527 /* start usb playback thread */
528 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
529 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
530 audio_extn_usb_start_playback(adev);
531
532 /* start usb capture thread */
533 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
534 audio_extn_usb_start_capture(adev);
535
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800536 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
537 audio_extn_spkr_prot_is_enabled()) {
538 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700539 adev->snd_dev_ref_cnt[snd_device]--;
540 return -EINVAL;
541 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200542 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800543 if (audio_extn_spkr_prot_start_processing(snd_device)) {
544 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200545 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800546 return -EINVAL;
547 }
548 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700549 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700550 /* due to the possibility of calibration overwrite between listen
551 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700552 audio_extn_sound_trigger_update_device_status(snd_device,
553 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530554 audio_extn_listen_update_device_status(snd_device,
555 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700556 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700557 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700558 audio_extn_sound_trigger_update_device_status(snd_device,
559 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530560 audio_extn_listen_update_device_status(snd_device,
561 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700562 return -EINVAL;
563 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300564 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700565 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530566
567 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
568 !adev->native_playback_enabled &&
569 audio_is_true_native_stream_active(adev)) {
570 ALOGD("%s: %d: napb: enabling native mode in hardware",
571 __func__, __LINE__);
572 audio_route_apply_and_update_path(adev->audio_route,
573 "true-native-mode");
574 adev->native_playback_enabled = true;
575 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800576 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800577 return 0;
578}
579
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700580int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700581 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800582{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700583 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
584
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800585 if (snd_device < SND_DEVICE_MIN ||
586 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800587 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800588 return -EINVAL;
589 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700590 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
591 ALOGE("%s: device ref cnt is already 0", __func__);
592 return -EINVAL;
593 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700594
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700596
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700597 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
598 ALOGE("%s: Invalid sound device returned", __func__);
599 return -EINVAL;
600 }
601
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700602 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700603 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800604 /* exit usb play back thread */
605 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
606 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
607 audio_extn_usb_stop_playback();
608
609 /* exit usb capture thread */
610 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700611 audio_extn_usb_stop_capture();
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800612
613 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
614 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700615 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300616 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700617 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300618 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700619
Ashish Jain81eb2a82015-05-13 10:52:34 +0530620 if (snd_device == SND_DEVICE_OUT_HDMI)
621 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530622 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
623 adev->native_playback_enabled) {
624 ALOGD("%s: %d: napb: disabling native mode in hardware",
625 __func__, __LINE__);
626 audio_route_reset_and_update_path(adev->audio_route,
627 "true-native-mode");
628 adev->native_playback_enabled = false;
629 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530630
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200631 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700632 audio_extn_sound_trigger_update_device_status(snd_device,
633 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530634 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800635 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700636 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700637
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800638 return 0;
639}
640
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700641static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530642 struct audio_usecase *uc_info,
643 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700644{
645 struct listnode *node;
646 struct audio_usecase *usecase;
647 bool switch_device[AUDIO_USECASE_MAX];
648 int i, num_uc_to_switch = 0;
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530649 int backend_idx = DEFAULT_CODEC_BACKEND;
650 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700651
652 /*
653 * This function is to make sure that all the usecases that are active on
654 * the hardware codec backend are always routed to any one device that is
655 * handled by the hardware codec.
656 * For example, if low-latency and deep-buffer usecases are currently active
657 * on speaker and out_set_parameters(headset) is received on low-latency
658 * output, then we have to make sure deep-buffer is also switched to headset,
659 * because of the limitation that both the devices cannot be enabled
660 * at the same time as they share the same backend.
661 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700662 /*
663 * This call is to check if we need to force routing for a particular stream
664 * If there is a backend configuration change for the device when a
665 * new stream starts, then ADM needs to be closed and re-opened with the new
666 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800667 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700668 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800669 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
670 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530671
672 ALOGD("%s:becf: force routing %d", __func__, force_routing);
673
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530674 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800676 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800677 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700678 for (i = 0; i < AUDIO_USECASE_MAX; i++)
679 switch_device[i] = false;
680
681 list_for_each(node, &adev->usecase_list) {
682 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800683
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530684 if (usecase == uc_info)
685 continue;
686 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
687
688 ALOGD("%s:becf: (%d) check_usecases backend_idx: %d,"
689 "usecase_backend_idx: %d, curr device: %s, usecase device:%s",
690 __func__, i, backend_idx, usecase_backend_idx,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530691 platform_get_snd_device_name(snd_device),
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530692 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800693
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800694 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530695 (usecase->out_snd_device != snd_device || force_routing) &&
696 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
697 usecase_backend_idx == backend_idx) {
698 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
699 __func__, use_case_table[usecase->id],
700 platform_get_snd_device_name(usecase->out_snd_device));
701 disable_audio_route(adev, usecase);
702 switch_device[usecase->id] = true;
703 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700704 }
705 }
706
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530707 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
708 num_uc_to_switch);
709
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700710 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700711 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700712
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530713 /* Make sure the previous devices to be disabled first and then enable the
714 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700715 list_for_each(node, &adev->usecase_list) {
716 usecase = node_to_item(node, struct audio_usecase, list);
717 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700718 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700719 }
720 }
721
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700722 list_for_each(node, &adev->usecase_list) {
723 usecase = node_to_item(node, struct audio_usecase, list);
724 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700725 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700726 }
727 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700728
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700729 /* Re-route all the usecases on the shared backend other than the
730 specified usecase to new snd devices */
731 list_for_each(node, &adev->usecase_list) {
732 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530733 /* Update the out_snd_device only before enabling the audio route */
734 if (switch_device[usecase->id]) {
735 usecase->out_snd_device = snd_device;
736 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530737 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530738 use_case_table[usecase->id],
739 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530740 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530741 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700742 }
743 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744 }
745}
746
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700747static void check_and_route_capture_usecases(struct audio_device *adev,
748 struct audio_usecase *uc_info,
749 snd_device_t snd_device)
750{
751 struct listnode *node;
752 struct audio_usecase *usecase;
753 bool switch_device[AUDIO_USECASE_MAX];
754 int i, num_uc_to_switch = 0;
755
756 /*
757 * This function is to make sure that all the active capture usecases
758 * are always routed to the same input sound device.
759 * For example, if audio-record and voice-call usecases are currently
760 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
761 * is received for voice call then we have to make sure that audio-record
762 * usecase is also switched to earpiece i.e. voice-dmic-ef,
763 * because of the limitation that two devices cannot be enabled
764 * at the same time if they share the same backend.
765 */
766 for (i = 0; i < AUDIO_USECASE_MAX; i++)
767 switch_device[i] = false;
768
769 list_for_each(node, &adev->usecase_list) {
770 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800771 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700772 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700773 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700774 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530775 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
776 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700777 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700778 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
779 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700780 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700781 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700782 switch_device[usecase->id] = true;
783 num_uc_to_switch++;
784 }
785 }
786
787 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700788 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700789
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530790 /* Make sure the previous devices to be disabled first and then enable the
791 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700792 list_for_each(node, &adev->usecase_list) {
793 usecase = node_to_item(node, struct audio_usecase, list);
794 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700795 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800796 }
797 }
798
799 list_for_each(node, &adev->usecase_list) {
800 usecase = node_to_item(node, struct audio_usecase, list);
801 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700802 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700803 }
804 }
805
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700806 /* Re-route all the usecases on the shared backend other than the
807 specified usecase to new snd devices */
808 list_for_each(node, &adev->usecase_list) {
809 usecase = node_to_item(node, struct audio_usecase, list);
810 /* Update the in_snd_device only before enabling the audio route */
811 if (switch_device[usecase->id] ) {
812 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800813 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530814 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700815 }
816 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700817 }
818}
819
Mingming Yin3a941d42016-02-17 18:08:05 -0800820static void reset_hdmi_sink_caps(struct stream_out *out) {
821 int i = 0;
822
823 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
824 out->supported_channel_masks[i] = 0;
825 }
826 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
827 out->supported_formats[i] = 0;
828 }
829 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
830 out->supported_sample_rates[i] = 0;
831 }
832}
833
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800834/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -0800835static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800836{
Mingming Yin3a941d42016-02-17 18:08:05 -0800837 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700838 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800839
Mingming Yin3a941d42016-02-17 18:08:05 -0800840 reset_hdmi_sink_caps(out);
841
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800842 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800843 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -0800844 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700845 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -0800846 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
847 case 6:
848 ALOGV("%s: HDMI supports 5.1 channels", __func__);
849 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
850 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
851 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
852 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
853 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
854 case 2:
855 ALOGV("%s: HDMI supports 2 channels", __func__);
856 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_STEREO;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800857 break;
858 default:
Mingming Yin3a941d42016-02-17 18:08:05 -0800859 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700860 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800861 break;
862 }
Mingming Yin3a941d42016-02-17 18:08:05 -0800863
864 // check channel format caps
865 i = 0;
866 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
867 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
868 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
869 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
870 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
871 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
872 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
873 }
874
875 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
876 ALOGV(":%s HDMI supports DTS format", __func__);
877 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
878 }
879
880 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
881 ALOGV(":%s HDMI supports DTS HD format", __func__);
882 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
883 }
884
885
886 // check sample rate caps
887 i = 0;
888 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
889 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
890 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
891 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
892 }
893 }
894
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700895 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800896}
897
Alexy Josephb1379942016-01-29 15:49:38 -0800898audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800899 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700900{
901 struct audio_usecase *usecase;
902 struct listnode *node;
903
904 list_for_each(node, &adev->usecase_list) {
905 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800906 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700907 ALOGV("%s: usecase id %d", __func__, usecase->id);
908 return usecase->id;
909 }
910 }
911 return USECASE_INVALID;
912}
913
Alexy Josephb1379942016-01-29 15:49:38 -0800914struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700915 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916{
917 struct audio_usecase *usecase;
918 struct listnode *node;
919
920 list_for_each(node, &adev->usecase_list) {
921 usecase = node_to_item(node, struct audio_usecase, list);
922 if (usecase->id == uc_id)
923 return usecase;
924 }
925 return NULL;
926}
927
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530928/*
929 * is a true native playback active
930 */
931bool audio_is_true_native_stream_active(struct audio_device *adev)
932{
933 bool active = false;
934 int i = 0;
935 struct listnode *node;
936
937 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
938 ALOGV("%s:napb: not in true mode or non hdphones device",
939 __func__);
940 active = false;
941 goto exit;
942 }
943
944 list_for_each(node, &adev->usecase_list) {
945 struct audio_usecase *uc;
946 uc = node_to_item(node, struct audio_usecase, list);
947 struct stream_out *curr_out =
948 (struct stream_out*) uc->stream.out;
949
950 if (curr_out && PCM_PLAYBACK == uc->type) {
951 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
952 "(%d) device %s", __func__, i++, use_case_table[uc->id],
953 uc->id, curr_out->sample_rate,
954 curr_out->bit_width,
955 platform_get_snd_device_name(uc->out_snd_device));
956
957 if (is_offload_usecase(uc->id) &&
958 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
959 active = true;
960 ALOGD("%s:napb:native stream detected", __func__);
961 }
962 }
963 }
964exit:
965 return active;
966}
967
968
969static bool force_device_switch(struct audio_usecase *usecase)
970{
971 bool ret = false;
972 bool is_it_true_mode = false;
973
974 if (is_offload_usecase(usecase->id) &&
975 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +0800976 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
977 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
978 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530979 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
980 if ((is_it_true_mode && !adev->native_playback_enabled) ||
981 (!is_it_true_mode && adev->native_playback_enabled)){
982 ret = true;
983 ALOGD("napb: time to toggle native mode");
984 }
985 }
986
987 return ret;
988}
989
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700990int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800991{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800992 snd_device_t out_snd_device = SND_DEVICE_NONE;
993 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700994 struct audio_usecase *usecase = NULL;
995 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800996 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800997 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800998 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700999 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001000
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301001 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1002
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001003 usecase = get_usecase_from_list(adev, uc_id);
1004 if (usecase == NULL) {
1005 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1006 return -EINVAL;
1007 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001008
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001009 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001010 (usecase->type == VOIP_CALL) ||
1011 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001012 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001013 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001014 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001015 usecase->devices = usecase->stream.out->devices;
1016 } else {
1017 /*
1018 * If the voice call is active, use the sound devices of voice call usecase
1019 * so that it would not result any device switch. All the usecases will
1020 * be switched to new device when select_devices() is called for voice call
1021 * usecase. This is to avoid switching devices for voice call when
1022 * check_usecases_codec_backend() is called below.
1023 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001024 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001025 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001026 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001027 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1028 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001029 in_snd_device = vc_usecase->in_snd_device;
1030 out_snd_device = vc_usecase->out_snd_device;
1031 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001032 } else if (voice_extn_compress_voip_is_active(adev)) {
1033 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001034 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +05301035 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001036 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001037 in_snd_device = voip_usecase->in_snd_device;
1038 out_snd_device = voip_usecase->out_snd_device;
1039 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001040 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001041 hfp_ucid = audio_extn_hfp_get_usecase();
1042 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001043 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001044 in_snd_device = hfp_usecase->in_snd_device;
1045 out_snd_device = hfp_usecase->out_snd_device;
1046 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001047 }
1048 if (usecase->type == PCM_PLAYBACK) {
1049 usecase->devices = usecase->stream.out->devices;
1050 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001051 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001052 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001053 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001054 if (usecase->stream.out == adev->primary_output &&
1055 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001056 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001057 select_devices(adev, adev->active_input->usecase);
1058 }
1059 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001060 } else if (usecase->type == PCM_CAPTURE) {
1061 usecase->devices = usecase->stream.in->device;
1062 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001063 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001064 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001065 if (adev->active_input &&
1066 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301067 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1068 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1069 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001070 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001071 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001072 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1073 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001074 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001075 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001076 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001077 }
1078 }
1079
1080 if (out_snd_device == usecase->out_snd_device &&
1081 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301082
1083 if (!force_device_switch(usecase))
1084 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001085 }
1086
sangwoobc677242013-08-08 16:53:43 +09001087 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001088 out_snd_device, platform_get_snd_device_name(out_snd_device),
1089 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001090
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001091 /*
1092 * Limitation: While in call, to do a device switch we need to disable
1093 * and enable both RX and TX devices though one of them is same as current
1094 * device.
1095 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001096 if ((usecase->type == VOICE_CALL) &&
1097 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1098 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001099 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001100 }
1101
1102 if (((usecase->type == VOICE_CALL) ||
1103 (usecase->type == VOIP_CALL)) &&
1104 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1105 /* Disable sidetone only if voice/voip call already exists */
1106 if (voice_is_call_state_active(adev) ||
1107 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001108 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001109 }
1110
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001111 /* Disable current sound devices */
1112 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001113 disable_audio_route(adev, usecase);
1114 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001115 }
1116
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001117 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001118 disable_audio_route(adev, usecase);
1119 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001120 }
1121
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001122 /* Applicable only on the targets that has external modem.
1123 * New device information should be sent to modem before enabling
1124 * the devices to reduce in-call device switch time.
1125 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001126 if ((usecase->type == VOICE_CALL) &&
1127 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1128 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001129 status = platform_switch_voice_call_enable_device_config(adev->platform,
1130 out_snd_device,
1131 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001132 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001133
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 /* Enable new sound devices */
1135 if (out_snd_device != SND_DEVICE_NONE) {
1136 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
1137 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001138 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001139 }
1140
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001141 if (in_snd_device != SND_DEVICE_NONE) {
1142 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001143 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001144 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001145
Avinash Vaish71a8b972014-07-24 15:36:33 +05301146 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001147 status = platform_switch_voice_call_device_post(adev->platform,
1148 out_snd_device,
1149 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301150 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001151 /* Enable sidetone only if voice/voip call already exists */
1152 if (voice_is_call_state_active(adev) ||
1153 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001154 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301155 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001156
sangwoo170731f2013-06-08 15:36:36 +09001157 usecase->in_snd_device = in_snd_device;
1158 usecase->out_snd_device = out_snd_device;
1159
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301160 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001161 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301162 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001163 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301164 usecase->stream.out->flags,
1165 usecase->stream.out->format,
1166 usecase->stream.out->sample_rate,
1167 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301168 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301169 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001170 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301171 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001172
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001173 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001174
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001175 /* Applicable only on the targets that has external modem.
1176 * Enable device command should be sent to modem only after
1177 * enabling voice call mixer controls
1178 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001179 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001180 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1181 out_snd_device,
1182 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301183 ALOGD("%s: done",__func__);
1184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001185 return status;
1186}
1187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001188static int stop_input_stream(struct stream_in *in)
1189{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301190 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001191 struct audio_usecase *uc_info;
1192 struct audio_device *adev = in->dev;
1193
Eric Laurentc8400632013-02-14 19:04:54 -08001194 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001195
Eric Laurent994a6932013-07-17 11:51:42 -07001196 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001197 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001198 uc_info = get_usecase_from_list(adev, in->usecase);
1199 if (uc_info == NULL) {
1200 ALOGE("%s: Could not find the usecase (%d) in the list",
1201 __func__, in->usecase);
1202 return -EINVAL;
1203 }
1204
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001205 /* Close in-call recording streams */
1206 voice_check_and_stop_incall_rec_usecase(adev, in);
1207
Eric Laurent150dbfe2013-02-27 14:31:02 -08001208 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001209 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001210
1211 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001212 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001213
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001214 list_remove(&uc_info->list);
1215 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001216
Eric Laurent994a6932013-07-17 11:51:42 -07001217 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001218 return ret;
1219}
1220
1221int start_input_stream(struct stream_in *in)
1222{
1223 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001224 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001225 struct audio_usecase *uc_info;
1226 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301227 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001228
Mingming Yin2664a5b2015-09-03 10:53:11 -07001229 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1230 if (get_usecase_from_list(adev, usecase) == NULL)
1231 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301232 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1233 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001234
Naresh Tanniru80659832014-06-04 18:17:56 +05301235
1236 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301237 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301238 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301239 goto error_config;
1240 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301241
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001242 /* Check if source matches incall recording usecase criteria */
1243 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1244 if (ret)
1245 goto error_config;
1246 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001247 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1248
1249 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1250 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1251 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1252 goto error_config;
1253 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001254
Eric Laurentb23d5282013-05-14 15:27:20 -07001255 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001256 if (in->pcm_device_id < 0) {
1257 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1258 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001259 ret = -EINVAL;
1260 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001261 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001262
1263 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001264 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001265
1266 if (!uc_info) {
1267 ret = -ENOMEM;
1268 goto error_config;
1269 }
1270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001271 uc_info->id = in->usecase;
1272 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001273 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001274 uc_info->devices = in->device;
1275 uc_info->in_snd_device = SND_DEVICE_NONE;
1276 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001277
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001278 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301279 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1280 adev->perf_lock_opts,
1281 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001282 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001283
Eric Laurentc8400632013-02-14 19:04:54 -08001284 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001285 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1286
1287 unsigned int flags = PCM_IN;
1288 unsigned int pcm_open_retry_count = 0;
1289
1290 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1291 flags |= PCM_MMAP | PCM_NOIRQ;
1292 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1293 }
1294
1295 while (1) {
1296 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1297 flags, &in->config);
1298 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1299 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1300 if (in->pcm != NULL) {
1301 pcm_close(in->pcm);
1302 in->pcm = NULL;
1303 }
1304 if (pcm_open_retry_count-- == 0) {
1305 ret = -EIO;
1306 goto error_open;
1307 }
1308 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1309 continue;
1310 }
1311 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001312 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001313
1314 ALOGV("%s: pcm_prepare", __func__);
1315 ret = pcm_prepare(in->pcm);
1316 if (ret < 0) {
1317 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1318 pcm_close(in->pcm);
1319 in->pcm = NULL;
1320 goto error_open;
1321 }
1322
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301323 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001324 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001325
Eric Laurentc8400632013-02-14 19:04:54 -08001326 return ret;
1327
1328error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301329 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001330 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001331error_config:
1332 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301333 /*
1334 * sleep 50ms to allow sufficient time for kernel
1335 * drivers to recover incases like SSR.
1336 */
1337 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001338 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001339
1340 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001341}
1342
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001343void lock_input_stream(struct stream_in *in)
1344{
1345 pthread_mutex_lock(&in->pre_lock);
1346 pthread_mutex_lock(&in->lock);
1347 pthread_mutex_unlock(&in->pre_lock);
1348}
1349
1350void lock_output_stream(struct stream_out *out)
1351{
1352 pthread_mutex_lock(&out->pre_lock);
1353 pthread_mutex_lock(&out->lock);
1354 pthread_mutex_unlock(&out->pre_lock);
1355}
1356
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001357/* must be called with out->lock locked */
1358static int send_offload_cmd_l(struct stream_out* out, int command)
1359{
1360 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1361
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001362 if (!cmd) {
1363 ALOGE("failed to allocate mem for command 0x%x", command);
1364 return -ENOMEM;
1365 }
1366
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001367 ALOGVV("%s %d", __func__, command);
1368
1369 cmd->cmd = command;
1370 list_add_tail(&out->offload_cmd_list, &cmd->node);
1371 pthread_cond_signal(&out->offload_cond);
1372 return 0;
1373}
1374
1375/* must be called iwth out->lock locked */
1376static void stop_compressed_output_l(struct stream_out *out)
1377{
1378 out->offload_state = OFFLOAD_STATE_IDLE;
1379 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001380 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001381 if (out->compr != NULL) {
1382 compress_stop(out->compr);
1383 while (out->offload_thread_blocked) {
1384 pthread_cond_wait(&out->cond, &out->lock);
1385 }
1386 }
1387}
1388
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001389bool is_offload_usecase(audio_usecase_t uc_id)
1390{
1391 unsigned int i;
1392 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1393 if (uc_id == offload_usecases[i])
1394 return true;
1395 }
1396 return false;
1397}
1398
vivek mehta446c3962015-09-14 10:57:35 -07001399static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001400{
vivek mehta446c3962015-09-14 10:57:35 -07001401 audio_usecase_t ret_uc = USECASE_INVALID;
1402 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001403 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001404 if (!adev->multi_offload_enable) {
1405 if (is_direct_pcm)
1406 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1407 else
1408 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001409
vivek mehta446c3962015-09-14 10:57:35 -07001410 pthread_mutex_lock(&adev->lock);
1411 if (get_usecase_from_list(adev, ret_uc) != NULL)
1412 ret_uc = USECASE_INVALID;
1413 pthread_mutex_unlock(&adev->lock);
1414
1415 return ret_uc;
1416 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001417
1418 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001419 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1420 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1421 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1422 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001423 break;
1424 }
1425 }
vivek mehta446c3962015-09-14 10:57:35 -07001426
1427 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1428 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001429}
1430
1431static void free_offload_usecase(struct audio_device *adev,
1432 audio_usecase_t uc_id)
1433{
vivek mehta446c3962015-09-14 10:57:35 -07001434 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001435 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001436
1437 if (!adev->multi_offload_enable)
1438 return;
1439
1440 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1441 if (offload_usecases[offload_uc_index] == uc_id) {
1442 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001443 break;
1444 }
1445 }
1446 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1447}
1448
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001449static void *offload_thread_loop(void *context)
1450{
1451 struct stream_out *out = (struct stream_out *) context;
1452 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001453 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001454
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001455 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1456 set_sched_policy(0, SP_FOREGROUND);
1457 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1458
1459 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001460 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001461 for (;;) {
1462 struct offload_cmd *cmd = NULL;
1463 stream_callback_event_t event;
1464 bool send_callback = false;
1465
1466 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1467 __func__, list_empty(&out->offload_cmd_list),
1468 out->offload_state);
1469 if (list_empty(&out->offload_cmd_list)) {
1470 ALOGV("%s SLEEPING", __func__);
1471 pthread_cond_wait(&out->offload_cond, &out->lock);
1472 ALOGV("%s RUNNING", __func__);
1473 continue;
1474 }
1475
1476 item = list_head(&out->offload_cmd_list);
1477 cmd = node_to_item(item, struct offload_cmd, node);
1478 list_remove(item);
1479
1480 ALOGVV("%s STATE %d CMD %d out->compr %p",
1481 __func__, out->offload_state, cmd->cmd, out->compr);
1482
1483 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1484 free(cmd);
1485 break;
1486 }
1487
1488 if (out->compr == NULL) {
1489 ALOGE("%s: Compress handle is NULL", __func__);
1490 pthread_cond_signal(&out->cond);
1491 continue;
1492 }
1493 out->offload_thread_blocked = true;
1494 pthread_mutex_unlock(&out->lock);
1495 send_callback = false;
1496 switch(cmd->cmd) {
1497 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001498 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001499 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001500 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001501 send_callback = true;
1502 event = STREAM_CBK_EVENT_WRITE_READY;
1503 break;
1504 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001505 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301506 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001507 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301508 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001509 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301510 if (ret < 0)
1511 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301512 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301513 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001514 compress_drain(out->compr);
1515 else
1516 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301517 if (ret != -ENETRESET) {
1518 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301519 pthread_mutex_lock(&out->lock);
1520 out->send_new_metadata = 1;
1521 out->send_next_track_params = true;
1522 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301523 event = STREAM_CBK_EVENT_DRAIN_READY;
1524 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1525 } else
1526 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001527 break;
1528 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001529 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001530 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001531 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001532 send_callback = true;
1533 event = STREAM_CBK_EVENT_DRAIN_READY;
1534 break;
1535 default:
1536 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1537 break;
1538 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001539 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001540 out->offload_thread_blocked = false;
1541 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001542 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001543 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001544 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001545 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001546 free(cmd);
1547 }
1548
1549 pthread_cond_signal(&out->cond);
1550 while (!list_empty(&out->offload_cmd_list)) {
1551 item = list_head(&out->offload_cmd_list);
1552 list_remove(item);
1553 free(node_to_item(item, struct offload_cmd, node));
1554 }
1555 pthread_mutex_unlock(&out->lock);
1556
1557 return NULL;
1558}
1559
1560static int create_offload_callback_thread(struct stream_out *out)
1561{
1562 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1563 list_init(&out->offload_cmd_list);
1564 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1565 offload_thread_loop, out);
1566 return 0;
1567}
1568
1569static int destroy_offload_callback_thread(struct stream_out *out)
1570{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001571 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001572 stop_compressed_output_l(out);
1573 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1574
1575 pthread_mutex_unlock(&out->lock);
1576 pthread_join(out->offload_thread, (void **) NULL);
1577 pthread_cond_destroy(&out->offload_cond);
1578
1579 return 0;
1580}
1581
Mingming Yin21854652016-04-13 11:54:02 -07001582static bool allow_hdmi_channel_config(struct audio_device *adev,
1583 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001584{
1585 struct listnode *node;
1586 struct audio_usecase *usecase;
1587 bool ret = true;
1588
Mingming Yin21854652016-04-13 11:54:02 -07001589 if (enable_passthru && !audio_extn_passthru_is_enabled()) {
1590 ret = false;
1591 goto exit;
1592 }
1593
1594 if (audio_extn_passthru_is_active()) {
1595 ALOGI("%s: Compress audio passthrough is active,"
1596 "no HDMI config change allowed", __func__);
1597 ret = false;
1598 goto exit;
1599 }
1600
Eric Laurent07eeafd2013-10-06 12:52:49 -07001601 list_for_each(node, &adev->usecase_list) {
1602 usecase = node_to_item(node, struct audio_usecase, list);
1603 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1604 /*
1605 * If voice call is already existing, do not proceed further to avoid
1606 * disabling/enabling both RX and TX devices, CSD calls, etc.
1607 * Once the voice call done, the HDMI channels can be configured to
1608 * max channels of remaining use cases.
1609 */
1610 if (usecase->id == USECASE_VOICE_CALL) {
Mingming Yin21854652016-04-13 11:54:02 -07001611 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001612 __func__);
1613 ret = false;
1614 break;
1615 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Mingming Yin21854652016-04-13 11:54:02 -07001616 if (!enable_passthru) {
1617 ALOGV("%s: multi channel playback is active, "
1618 "no change in HDMI channels", __func__);
1619 ret = false;
1620 break;
1621 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001622 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001623 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin21854652016-04-13 11:54:02 -07001624 if (!enable_passthru) {
1625 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1626 ", no change in HDMI channels", __func__,
1627 usecase->stream.out->channel_mask);
1628 ret = false;
1629 break;
1630 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001631 }
1632 }
1633 }
Mingming Yin21854652016-04-13 11:54:02 -07001634 ALOGV("allow hdmi config %d", ret);
1635exit:
Eric Laurent07eeafd2013-10-06 12:52:49 -07001636 return ret;
1637}
1638
Mingming Yin21854652016-04-13 11:54:02 -07001639static int check_and_set_hdmi_config(struct audio_device *adev,
1640 uint32_t channels,
1641 uint32_t sample_rate,
1642 audio_format_t format,
1643 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001644{
1645 struct listnode *node;
1646 struct audio_usecase *usecase;
Mingming Yin21854652016-04-13 11:54:02 -07001647 int32_t factor = 1;
1648 bool config = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001649
Mingming Yin21854652016-04-13 11:54:02 -07001650 ALOGV("%s channels %d sample_rate %d format:%x enable_passthru:%d",
1651 __func__, channels, sample_rate, format, enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001652
Mingming Yin21854652016-04-13 11:54:02 -07001653 if (channels != adev->cur_hdmi_channels) {
1654 ALOGV("channel does not match current hdmi channels");
1655 config = true;
1656 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001657
Mingming Yin21854652016-04-13 11:54:02 -07001658 if (sample_rate != adev->cur_hdmi_sample_rate) {
1659 ALOGV("sample rate does not match current hdmi sample rate");
1660 config = true;
1661 }
1662
1663 if (format != adev->cur_hdmi_format) {
1664 ALOGV("format does not match current hdmi format");
1665 config = true;
1666 }
1667
1668 /* TBD - add check for bit width */
1669 if (!config) {
1670 ALOGV("No need to config hdmi");
Eric Laurent07eeafd2013-10-06 12:52:49 -07001671 return 0;
1672 }
1673
Mingming Yin21854652016-04-13 11:54:02 -07001674 if (enable_passthru &&
1675 (format == AUDIO_FORMAT_E_AC3)) {
1676 ALOGV("factor 4 for E_AC3 passthru");
1677 factor = 4;
1678 }
1679
1680 platform_set_hdmi_config(adev->platform, channels, factor * sample_rate,
1681 enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001682 adev->cur_hdmi_channels = channels;
Mingming Yin21854652016-04-13 11:54:02 -07001683 adev->cur_hdmi_format = format;
1684 adev->cur_hdmi_sample_rate = sample_rate;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001685
1686 /*
1687 * Deroute all the playback streams routed to HDMI so that
1688 * the back end is deactivated. Note that backend will not
1689 * be deactivated if any one stream is connected to it.
1690 */
1691 list_for_each(node, &adev->usecase_list) {
1692 usecase = node_to_item(node, struct audio_usecase, list);
1693 if (usecase->type == PCM_PLAYBACK &&
1694 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001695 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001696 }
1697 }
1698
Mingming Yin21854652016-04-13 11:54:02 -07001699 bool was_active = audio_extn_keep_alive_is_active();
1700 if (was_active)
1701 audio_extn_keep_alive_stop();
1702
Eric Laurent07eeafd2013-10-06 12:52:49 -07001703 /*
1704 * Enable all the streams disabled above. Now the HDMI backend
1705 * will be activated with new channel configuration
1706 */
1707 list_for_each(node, &adev->usecase_list) {
1708 usecase = node_to_item(node, struct audio_usecase, list);
1709 if (usecase->type == PCM_PLAYBACK &&
1710 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001711 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001712 }
1713 }
1714
Mingming Yin21854652016-04-13 11:54:02 -07001715 if (was_active)
1716 audio_extn_keep_alive_start();
1717
Eric Laurent07eeafd2013-10-06 12:52:49 -07001718 return 0;
1719}
1720
Mingming Yin21854652016-04-13 11:54:02 -07001721/* called with out lock taken */
1722static int check_and_set_hdmi_backend(struct stream_out *out)
1723{
1724 struct audio_device *adev = out->dev;
1725 int ret;
1726 bool enable_passthru = false;
1727
1728 if (!(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL))
1729 return -1;
1730
1731 ALOGV("%s usecase %s out->format:%x out->bit_width:%d", __func__, use_case_table[out->usecase],out->format,out->bit_width);
1732
1733 if (is_offload_usecase(out->usecase) &&
1734 audio_extn_dolby_is_passthrough_stream(out)) {
1735 enable_passthru = true;
1736 }
1737
1738 /* Check if change in HDMI channel config is allowed */
1739 if (!allow_hdmi_channel_config(adev, enable_passthru)) {
1740 return -EPERM;
1741 }
1742
1743 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1744 uint32_t channels;
1745 ALOGV("Offload usecase, enable passthru %d", enable_passthru);
1746
1747 if (enable_passthru) {
1748 audio_extn_passthru_on_start(out);
1749 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1750 }
1751
1752 /* For pass through case, the backend should be configured as stereo */
1753 channels = enable_passthru ? DEFAULT_HDMI_OUT_CHANNELS :
1754 out->compr_config.codec->ch_in;
1755
1756 ret = check_and_set_hdmi_config(adev, channels,
1757 out->sample_rate, out->format,
1758 enable_passthru);
1759 } else
1760 ret = check_and_set_hdmi_config(adev, out->config.channels,
1761 out->config.rate,
1762 out->format,
1763 false);
1764 return ret;
1765}
1766
1767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768static int stop_output_stream(struct stream_out *out)
1769{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301770 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771 struct audio_usecase *uc_info;
1772 struct audio_device *adev = out->dev;
1773
Eric Laurent994a6932013-07-17 11:51:42 -07001774 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001775 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776 uc_info = get_usecase_from_list(adev, out->usecase);
1777 if (uc_info == NULL) {
1778 ALOGE("%s: Could not find the usecase (%d) in the list",
1779 __func__, out->usecase);
1780 return -EINVAL;
1781 }
1782
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001783 if (is_offload_usecase(out->usecase) &&
Mingming Yin21854652016-04-13 11:54:02 -07001784 !(audio_extn_dolby_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001785 if (adev->visualizer_stop_output != NULL)
1786 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001787
1788 audio_extn_dts_remove_state_notifier_node(out->usecase);
1789
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001790 if (adev->offload_effects_stop_output != NULL)
1791 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1792 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001793
Eric Laurent150dbfe2013-02-27 14:31:02 -08001794 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001795 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001796
1797 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001798 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001800 list_remove(&uc_info->list);
1801 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001802
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001803 if (is_offload_usecase(out->usecase) &&
Mingming Yin21854652016-04-13 11:54:02 -07001804 (audio_extn_dolby_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001805 ALOGV("Disable passthrough , reset mixer to pcm");
1806 /* NO_PASSTHROUGH */
1807 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001808
1809 /* Must be called after removing the usecase from list */
1810 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1811 check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
1812 DEFAULT_HDMI_OUT_SAMPLE_RATE,
1813 DEFAULT_HDMI_OUT_FORMAT,
1814 false);
1815 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001816 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1817 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001818
Eric Laurent994a6932013-07-17 11:51:42 -07001819 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001820 return ret;
1821}
1822
1823int start_output_stream(struct stream_out *out)
1824{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826 struct audio_usecase *uc_info;
1827 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301828 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001829
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001830 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1831 ret = -EINVAL;
1832 goto error_config;
1833 }
1834
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301835 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1836 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1837 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301838
Naresh Tanniru80659832014-06-04 18:17:56 +05301839 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301840 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301841 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301842 goto error_config;
1843 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301844
Eric Laurentb23d5282013-05-14 15:27:20 -07001845 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846 if (out->pcm_device_id < 0) {
1847 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1848 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001849 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001850 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851 }
1852
1853 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001854
1855 if (!uc_info) {
1856 ret = -ENOMEM;
1857 goto error_config;
1858 }
1859
Mingming Yin21854652016-04-13 11:54:02 -07001860 /* This must be called before adding this usecase to the list */
1861 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1862 /* This call can fail if compress pass thru is already active */
1863 check_and_set_hdmi_backend(out);
1864 }
1865
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001866 uc_info->id = out->usecase;
1867 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001868 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001869 uc_info->devices = out->devices;
1870 uc_info->in_snd_device = SND_DEVICE_NONE;
1871 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001872 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001873
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301874 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1875 adev->perf_lock_opts,
1876 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001877 select_devices(adev, out->usecase);
1878
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001879 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1880 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001881 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001882 unsigned int flags = PCM_OUT;
1883 unsigned int pcm_open_retry_count = 0;
1884 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1885 flags |= PCM_MMAP | PCM_NOIRQ;
1886 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1887 } else
1888 flags |= PCM_MONOTONIC;
1889
1890 while (1) {
1891 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1892 flags, &out->config);
1893 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1894 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1895 if (out->pcm != NULL) {
1896 pcm_close(out->pcm);
1897 out->pcm = NULL;
1898 }
1899 if (pcm_open_retry_count-- == 0) {
1900 ret = -EIO;
1901 goto error_open;
1902 }
1903 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1904 continue;
1905 }
1906 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001907 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001908
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001909 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1910 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001911
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001912 ALOGV("%s: pcm_prepare", __func__);
1913 if (pcm_is_ready(out->pcm)) {
1914 ret = pcm_prepare(out->pcm);
1915 if (ret < 0) {
1916 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1917 pcm_close(out->pcm);
1918 out->pcm = NULL;
1919 goto error_open;
1920 }
1921 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001922 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001923 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1924 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001925 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001926 out->compr = compress_open(adev->snd_card,
1927 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001928 COMPRESS_IN, &out->compr_config);
1929 if (out->compr && !is_compress_ready(out->compr)) {
1930 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1931 compress_close(out->compr);
1932 out->compr = NULL;
1933 ret = -EIO;
1934 goto error_open;
1935 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301936 /* compress_open sends params of the track, so reset the flag here */
1937 out->is_compr_metadata_avail = false;
1938
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001939 if (out->offload_callback)
1940 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001941
Fred Oh3f43e742015-03-04 18:42:34 -08001942 /* Since small bufs uses blocking writes, a write will be blocked
1943 for the default max poll time (20s) in the event of an SSR.
1944 Reduce the poll time to observe and deal with SSR faster.
1945 */
1946 if (out->use_small_bufs) {
1947 compress_set_max_poll_wait(out->compr, 1000);
1948 }
1949
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001950 audio_extn_dts_create_state_notifier_node(out->usecase);
1951 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1952 popcount(out->channel_mask),
1953 out->playback_started);
1954
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001955#ifdef DS1_DOLBY_DDP_ENABLED
1956 if (audio_extn_is_dolby_format(out->format))
1957 audio_extn_dolby_send_ddp_endp_params(adev);
1958#endif
Mingming Yin21854652016-04-13 11:54:02 -07001959 if (!(audio_extn_dolby_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001960 if (adev->visualizer_start_output != NULL)
1961 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1962 if (adev->offload_effects_start_output != NULL)
1963 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001964 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001965 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301967 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001968 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001971error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301972 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001974error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301975 /*
1976 * sleep 50ms to allow sufficient time for kernel
1977 * drivers to recover incases like SSR.
1978 */
1979 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001980 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001981}
1982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983static int check_input_parameters(uint32_t sample_rate,
1984 audio_format_t format,
1985 int channel_count)
1986{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001987 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001989 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001990 !voice_extn_compress_voip_is_format_supported(format) &&
1991 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001992
1993 switch (channel_count) {
1994 case 1:
1995 case 2:
1996 case 6:
1997 break;
1998 default:
1999 ret = -EINVAL;
2000 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001
2002 switch (sample_rate) {
2003 case 8000:
2004 case 11025:
2005 case 12000:
2006 case 16000:
2007 case 22050:
2008 case 24000:
2009 case 32000:
2010 case 44100:
2011 case 48000:
2012 break;
2013 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002014 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002015 }
2016
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002017 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002018}
2019
2020static size_t get_input_buffer_size(uint32_t sample_rate,
2021 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002022 int channel_count,
2023 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002024{
2025 size_t size = 0;
2026
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002027 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2028 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002030 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002031 if (is_low_latency)
2032 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002033 /* ToDo: should use frame_size computed based on the format and
2034 channel_count here. */
2035 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002036
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002037 /* make sure the size is multiple of 32 bytes
2038 * At 48 kHz mono 16-bit PCM:
2039 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2040 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2041 */
2042 size += 0x1f;
2043 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002044
2045 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002046}
2047
2048static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2049{
2050 struct stream_out *out = (struct stream_out *)stream;
2051
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002052 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002053}
2054
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002055static int out_set_sample_rate(struct audio_stream *stream __unused,
2056 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057{
2058 return -ENOSYS;
2059}
2060
2061static size_t out_get_buffer_size(const struct audio_stream *stream)
2062{
2063 struct stream_out *out = (struct stream_out *)stream;
2064
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002065 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002066 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002067 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2068 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002069
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002070 return out->config.period_size *
2071 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072}
2073
2074static uint32_t out_get_channels(const struct audio_stream *stream)
2075{
2076 struct stream_out *out = (struct stream_out *)stream;
2077
2078 return out->channel_mask;
2079}
2080
2081static audio_format_t out_get_format(const struct audio_stream *stream)
2082{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002083 struct stream_out *out = (struct stream_out *)stream;
2084
2085 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002086}
2087
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002088static int out_set_format(struct audio_stream *stream __unused,
2089 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002090{
2091 return -ENOSYS;
2092}
2093
2094static int out_standby(struct audio_stream *stream)
2095{
2096 struct stream_out *out = (struct stream_out *)stream;
2097 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002098
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302099 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2100 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002101 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2102 /* Ignore standby in case of voip call because the voip output
2103 * stream is closed in adev_close_output_stream()
2104 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302105 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002106 return 0;
2107 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002108
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002109 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002111 if (adev->adm_deregister_stream)
2112 adev->adm_deregister_stream(adev->adm_data, out->handle);
2113
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002114 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002116 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002117 if (out->pcm) {
2118 pcm_close(out->pcm);
2119 out->pcm = NULL;
2120 }
2121 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002122 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002123 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302124 out->send_next_track_params = false;
2125 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002126 out->gapless_mdata.encoder_delay = 0;
2127 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002128 if (out->compr != NULL) {
2129 compress_close(out->compr);
2130 out->compr = NULL;
2131 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002132 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002133 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002134 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002135 }
2136 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302137 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138 return 0;
2139}
2140
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002141static int out_dump(const struct audio_stream *stream __unused,
2142 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143{
2144 return 0;
2145}
2146
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002147static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2148{
2149 int ret = 0;
2150 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002151
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002152 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002153 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002154 return -EINVAL;
2155 }
2156
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302157 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002158
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002159 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2160 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302161 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002162 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002163 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2164 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302165 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002166 }
2167
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002168 ALOGV("%s new encoder delay %u and padding %u", __func__,
2169 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2170
2171 return 0;
2172}
2173
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002174static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2175{
2176 return out == adev->primary_output || out == adev->voice_tx_output;
2177}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002178
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2180{
2181 struct stream_out *out = (struct stream_out *)stream;
2182 struct audio_device *adev = out->dev;
2183 struct str_parms *parms;
2184 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002185 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186
sangwoobc677242013-08-08 16:53:43 +09002187 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002188 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302190 if (!parms)
2191 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002192 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2193 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002195 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002196 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002197
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002198 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302199 * When HDMI cable is unplugged/usb hs is disconnected the
2200 * music playback is paused and the policy manager sends routing=0
2201 * But the audioflingercontinues to write data until standby time
2202 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002203 * Avoid this by routing audio to speaker until standby.
2204 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302205 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2206 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002207 val == AUDIO_DEVICE_NONE) {
Mingming Yin21854652016-04-13 11:54:02 -07002208 if (!audio_extn_dolby_is_passthrough_stream(out))
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08002209 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002210 }
2211
2212 /*
2213 * select_devices() call below switches all the usecases on the same
2214 * backend to the new device. Refer to check_usecases_codec_backend() in
2215 * the select_devices(). But how do we undo this?
2216 *
2217 * For example, music playback is active on headset (deep-buffer usecase)
2218 * and if we go to ringtones and select a ringtone, low-latency usecase
2219 * will be started on headset+speaker. As we can't enable headset+speaker
2220 * and headset devices at the same time, select_devices() switches the music
2221 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2222 * So when the ringtone playback is completed, how do we undo the same?
2223 *
2224 * We are relying on the out_set_parameters() call on deep-buffer output,
2225 * once the ringtone playback is ended.
2226 * NOTE: We should not check if the current devices are same as new devices.
2227 * Because select_devices() must be called to switch back the music
2228 * playback to headset.
2229 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002230 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002231 out->devices = val;
2232
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302233 if (!out->standby) {
2234 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2235 adev->perf_lock_opts,
2236 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002237 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302238 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2239 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002240
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002241 if (output_drives_call(adev, out)) {
2242 if(!voice_is_in_call(adev)) {
2243 if (adev->mode == AUDIO_MODE_IN_CALL) {
2244 adev->current_call_output = out;
2245 ret = voice_start_call(adev);
2246 }
2247 } else {
2248 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002249 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002250 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002251 }
2252 }
2253
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002255 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002257
2258 if (out == adev->primary_output) {
2259 pthread_mutex_lock(&adev->lock);
2260 audio_extn_set_parameters(adev, parms);
2261 pthread_mutex_unlock(&adev->lock);
2262 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002263 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002264 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002265 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002266
2267 audio_extn_dts_create_state_notifier_node(out->usecase);
2268 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2269 popcount(out->channel_mask),
2270 out->playback_started);
2271
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002272 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002273 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002275 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302276error:
Eric Laurent994a6932013-07-17 11:51:42 -07002277 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002278 return ret;
2279}
2280
2281static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2282{
2283 struct stream_out *out = (struct stream_out *)stream;
2284 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002285 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286 char value[256];
2287 struct str_parms *reply = str_parms_create();
2288 size_t i, j;
2289 int ret;
2290 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002291
2292 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002293 if (reply) {
2294 str_parms_destroy(reply);
2295 }
2296 if (query) {
2297 str_parms_destroy(query);
2298 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002299 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2300 return NULL;
2301 }
2302
Eric Laurent994a6932013-07-17 11:51:42 -07002303 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002304 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2305 if (ret >= 0) {
2306 value[0] = '\0';
2307 i = 0;
2308 while (out->supported_channel_masks[i] != 0) {
2309 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2310 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2311 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002312 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002314 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002315 first = false;
2316 break;
2317 }
2318 }
2319 i++;
2320 }
2321 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2322 str = str_parms_to_str(reply);
2323 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002324 voice_extn_out_get_parameters(out, query, reply);
2325 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002326 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002327 free(str);
2328 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002329 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002330 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002331
Alexy Joseph62142aa2015-11-16 15:10:34 -08002332
2333 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2334 if (ret >= 0) {
2335 value[0] = '\0';
2336 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2337 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302338 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002339 } else {
2340 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302341 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002342 }
2343 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002344 if (str)
2345 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002346 str = str_parms_to_str(reply);
2347 }
2348
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002349 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2350 if (ret >= 0) {
2351 value[0] = '\0';
2352 i = 0;
2353 first = true;
2354 while (out->supported_formats[i] != 0) {
2355 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2356 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2357 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002358 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002359 }
2360 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2361 first = false;
2362 break;
2363 }
2364 }
2365 i++;
2366 }
2367 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002368 if (str)
2369 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002370 str = str_parms_to_str(reply);
2371 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002372
2373 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2374 if (ret >= 0) {
2375 value[0] = '\0';
2376 i = 0;
2377 first = true;
2378 while (out->supported_sample_rates[i] != 0) {
2379 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2380 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2381 if (!first) {
2382 strlcat(value, "|", sizeof(value));
2383 }
2384 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2385 first = false;
2386 break;
2387 }
2388 }
2389 i++;
2390 }
2391 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2392 if (str)
2393 free(str);
2394 str = str_parms_to_str(reply);
2395 }
2396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002397 str_parms_destroy(query);
2398 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002399 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002400 return str;
2401}
2402
2403static uint32_t out_get_latency(const struct audio_stream_out *stream)
2404{
2405 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002406 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002407
Alexy Josephaa54c872014-12-03 02:46:47 -08002408 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002409 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002410 } else {
2411 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002412 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002413 }
2414
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302415 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002416 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002417}
2418
2419static int out_set_volume(struct audio_stream_out *stream, float left,
2420 float right)
2421{
Eric Laurenta9024de2013-04-04 09:19:12 -07002422 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002423 int volume[2];
2424
Eric Laurenta9024de2013-04-04 09:19:12 -07002425 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2426 /* only take left channel into account: the API is for stereo anyway */
2427 out->muted = (left == 0.0f);
2428 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002429 } else if (is_offload_usecase(out->usecase)) {
Mingming Yin21854652016-04-13 11:54:02 -07002430 if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002431 /*
2432 * Set mute or umute on HDMI passthrough stream.
2433 * Only take left channel into account.
2434 * Mute is 0 and unmute 1
2435 */
2436 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2437 } else {
2438 char mixer_ctl_name[128];
2439 struct audio_device *adev = out->dev;
2440 struct mixer_ctl *ctl;
2441 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002442 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002443
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002444 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2445 "Compress Playback %d Volume", pcm_device_id);
2446 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2447 if (!ctl) {
2448 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2449 __func__, mixer_ctl_name);
2450 return -EINVAL;
2451 }
2452 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2453 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2454 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2455 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002456 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002457 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002459 return -ENOSYS;
2460}
2461
2462static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2463 size_t bytes)
2464{
2465 struct stream_out *out = (struct stream_out *)stream;
2466 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302467 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002468 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002470 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302471
Naresh Tanniru80659832014-06-04 18:17:56 +05302472 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002473
Ashish Jainbbce4322016-02-16 13:25:27 +05302474 if (is_offload_usecase(out->usecase)) {
2475 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302476 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2477 pthread_mutex_unlock(&out->lock);
2478 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302479 } else {
2480 /* increase written size during SSR to avoid mismatch
2481 * with the written frames count in AF
2482 */
2483 out->written += bytes / (out->config.channels * sizeof(short));
2484 ALOGD(" %s: sound card is not active/SSR state", __func__);
2485 ret= -EIO;
2486 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302487 }
2488 }
2489
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002491 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002492 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002493 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2494 ret = voice_extn_compress_voip_start_output_stream(out);
2495 else
2496 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002497 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002498 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002500 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501 goto exit;
2502 }
vivek mehta446c3962015-09-14 10:57:35 -07002503 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002504 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506
Ashish Jain81eb2a82015-05-13 10:52:34 +05302507 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002508 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302509 adev->is_channel_status_set = true;
2510 }
2511
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002512 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002513 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002514 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002515 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002516 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2517 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302518 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2519 ALOGD("copl(%p):send next track params in gapless", out);
2520 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2521 out->send_next_track_params = false;
2522 out->is_compr_metadata_avail = false;
2523 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002524 }
2525
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002526 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302527 if (ret < 0)
2528 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302529 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002530 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302531 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002532 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302533 } else if (-ENETRESET == ret) {
2534 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2535 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2536 pthread_mutex_unlock(&out->lock);
2537 out_standby(&out->stream.common);
2538 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002539 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302540 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002541 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002542 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002543 out->playback_started = 1;
2544 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002545
2546 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2547 popcount(out->channel_mask),
2548 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002549 }
2550 pthread_mutex_unlock(&out->lock);
2551 return ret;
2552 } else {
2553 if (out->pcm) {
2554 if (out->muted)
2555 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002556
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302557 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002558
2559 if (adev->adm_request_focus)
2560 adev->adm_request_focus(adev->adm_data, out->handle);
2561
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002562 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2563 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2564 else
2565 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002566
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302567 if (ret < 0)
2568 ret = -errno;
2569 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002570 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002571
2572 if (adev->adm_abandon_focus)
2573 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002574 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575 }
2576
2577exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302578 /* ToDo: There may be a corner case when SSR happens back to back during
2579 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302580 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302581 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302582 }
2583
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584 pthread_mutex_unlock(&out->lock);
2585
2586 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002587 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002588 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302589 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302590 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302591 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302592 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302593 out->standby = true;
2594 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302596 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302597 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598 }
2599 return bytes;
2600}
2601
2602static int out_get_render_position(const struct audio_stream_out *stream,
2603 uint32_t *dsp_frames)
2604{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002605 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302606 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002607
2608 if (dsp_frames == NULL)
2609 return -EINVAL;
2610
2611 *dsp_frames = 0;
2612 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002613 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002614 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002615 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302616 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002617 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302618 if (ret < 0)
2619 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002620 ALOGVV("%s rendered frames %d sample_rate %d",
2621 __func__, *dsp_frames, out->sample_rate);
2622 }
2623 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302624 if (-ENETRESET == ret) {
2625 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2626 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2627 return -EINVAL;
2628 } else if(ret < 0) {
2629 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2630 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302631 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2632 /*
2633 * Handle corner case where compress session is closed during SSR
2634 * and timestamp is queried
2635 */
2636 ALOGE(" ERROR: sound card not active, return error");
2637 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302638 } else {
2639 return 0;
2640 }
Zhou Song32a556e2015-05-05 10:46:56 +08002641 } else if (audio_is_linear_pcm(out->format)) {
2642 *dsp_frames = out->written;
2643 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002644 } else
2645 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002646}
2647
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002648static int out_add_audio_effect(const struct audio_stream *stream __unused,
2649 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650{
2651 return 0;
2652}
2653
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002654static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2655 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656{
2657 return 0;
2658}
2659
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002660static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2661 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662{
2663 return -EINVAL;
2664}
2665
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002666static int out_get_presentation_position(const struct audio_stream_out *stream,
2667 uint64_t *frames, struct timespec *timestamp)
2668{
2669 struct stream_out *out = (struct stream_out *)stream;
2670 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002671 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002672
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002673 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002674
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002675 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002676 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302677 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002678 &out->sample_rate);
2679 ALOGVV("%s rendered frames %ld sample_rate %d",
2680 __func__, dsp_frames, out->sample_rate);
2681 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302682 if (ret < 0)
2683 ret = -errno;
2684 if (-ENETRESET == ret) {
2685 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2686 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2687 ret = -EINVAL;
2688 } else
2689 ret = 0;
2690
Eric Laurent949a0892013-09-20 09:20:13 -07002691 /* this is the best we can do */
2692 clock_gettime(CLOCK_MONOTONIC, timestamp);
2693 }
2694 } else {
2695 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002696 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002697 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2698 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002699 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002700 // This adjustment accounts for buffering after app processor.
2701 // It is based on estimated DSP latency per use case, rather than exact.
2702 signed_frames -=
2703 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2704
Eric Laurent949a0892013-09-20 09:20:13 -07002705 // It would be unusual for this value to be negative, but check just in case ...
2706 if (signed_frames >= 0) {
2707 *frames = signed_frames;
2708 ret = 0;
2709 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002710 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302711 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2712 *frames = out->written;
2713 clock_gettime(CLOCK_MONOTONIC, timestamp);
2714 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002715 }
2716 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002717 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002718 return ret;
2719}
2720
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002721static int out_set_callback(struct audio_stream_out *stream,
2722 stream_callback_t callback, void *cookie)
2723{
2724 struct stream_out *out = (struct stream_out *)stream;
2725
2726 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002727 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002728 out->offload_callback = callback;
2729 out->offload_cookie = cookie;
2730 pthread_mutex_unlock(&out->lock);
2731 return 0;
2732}
2733
2734static int out_pause(struct audio_stream_out* stream)
2735{
2736 struct stream_out *out = (struct stream_out *)stream;
2737 int status = -ENOSYS;
2738 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002739 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002740 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002741 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002742 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302743 struct audio_device *adev = out->dev;
2744 int snd_scard_state = get_snd_card_state(adev);
2745
2746 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2747 status = compress_pause(out->compr);
2748
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002749 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002750
Mingming Yin21854652016-04-13 11:54:02 -07002751 if (audio_extn_passthru_is_active()) {
2752 ALOGV("offload use case, pause passthru");
2753 audio_extn_passthru_on_pause(out);
2754 }
2755
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302756 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002757 audio_extn_dts_notify_playback_state(out->usecase, 0,
2758 out->sample_rate, popcount(out->channel_mask),
2759 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002760 }
2761 pthread_mutex_unlock(&out->lock);
2762 }
2763 return status;
2764}
2765
2766static int out_resume(struct audio_stream_out* stream)
2767{
2768 struct stream_out *out = (struct stream_out *)stream;
2769 int status = -ENOSYS;
2770 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002771 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002772 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002773 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002774 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002775 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302776 struct audio_device *adev = out->dev;
2777 int snd_scard_state = get_snd_card_state(adev);
2778
Mingming Yin21854652016-04-13 11:54:02 -07002779 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
2780 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2781 pthread_mutex_lock(&out->dev->lock);
2782 ALOGV("offload resume, check and set hdmi backend again");
2783 check_and_set_hdmi_backend(out);
2784 pthread_mutex_unlock(&out->dev->lock);
2785 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302786 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07002787 }
2788 if (!status) {
2789 out->offload_state = OFFLOAD_STATE_PLAYING;
2790 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302791 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002792 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2793 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002794 }
2795 pthread_mutex_unlock(&out->lock);
2796 }
2797 return status;
2798}
2799
2800static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2801{
2802 struct stream_out *out = (struct stream_out *)stream;
2803 int status = -ENOSYS;
2804 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002805 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002806 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002807 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2808 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2809 else
2810 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2811 pthread_mutex_unlock(&out->lock);
2812 }
2813 return status;
2814}
2815
2816static int out_flush(struct audio_stream_out* stream)
2817{
2818 struct stream_out *out = (struct stream_out *)stream;
2819 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002820 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002821 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002822 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002823 stop_compressed_output_l(out);
2824 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002825 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002826 return 0;
2827 }
2828 return -ENOSYS;
2829}
2830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831/** audio_stream_in implementation **/
2832static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2833{
2834 struct stream_in *in = (struct stream_in *)stream;
2835
2836 return in->config.rate;
2837}
2838
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002839static int in_set_sample_rate(struct audio_stream *stream __unused,
2840 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002841{
2842 return -ENOSYS;
2843}
2844
2845static size_t in_get_buffer_size(const struct audio_stream *stream)
2846{
2847 struct stream_in *in = (struct stream_in *)stream;
2848
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002849 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2850 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002851 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2852 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002853
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002854 return in->config.period_size *
2855 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002856}
2857
2858static uint32_t in_get_channels(const struct audio_stream *stream)
2859{
2860 struct stream_in *in = (struct stream_in *)stream;
2861
2862 return in->channel_mask;
2863}
2864
2865static audio_format_t in_get_format(const struct audio_stream *stream)
2866{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002867 struct stream_in *in = (struct stream_in *)stream;
2868
2869 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870}
2871
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002872static int in_set_format(struct audio_stream *stream __unused,
2873 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002874{
2875 return -ENOSYS;
2876}
2877
2878static int in_standby(struct audio_stream *stream)
2879{
2880 struct stream_in *in = (struct stream_in *)stream;
2881 struct audio_device *adev = in->dev;
2882 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302883 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2884 stream, in->usecase, use_case_table[in->usecase]);
2885
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002886 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2887 /* Ignore standby in case of voip call because the voip input
2888 * stream is closed in adev_close_input_stream()
2889 */
2890 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2891 return status;
2892 }
2893
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002894 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002895 if (!in->standby && in->is_st_session) {
2896 ALOGD("%s: sound trigger pcm stop lab", __func__);
2897 audio_extn_sound_trigger_stop_lab(in);
2898 in->standby = 1;
2899 }
2900
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002901 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002902 if (adev->adm_deregister_stream)
2903 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2904
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002905 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002906 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002907 if (in->pcm) {
2908 pcm_close(in->pcm);
2909 in->pcm = NULL;
2910 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002911 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002912 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002913 }
2914 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002915 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002916 return status;
2917}
2918
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002919static int in_dump(const struct audio_stream *stream __unused,
2920 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002921{
2922 return 0;
2923}
2924
2925static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2926{
2927 struct stream_in *in = (struct stream_in *)stream;
2928 struct audio_device *adev = in->dev;
2929 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002930 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002931 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002932
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302933 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002934 parms = str_parms_create_str(kvpairs);
2935
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302936 if (!parms)
2937 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002938 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002939 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002940
2941 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2942 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002943 val = atoi(value);
2944 /* no audio source uses val == 0 */
2945 if ((in->source != val) && (val != 0)) {
2946 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002947 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2948 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2949 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08002950 (in->config.rate == 8000 || in->config.rate == 16000 ||
2951 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002952 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002953 err = voice_extn_compress_voip_open_input_stream(in);
2954 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002955 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002956 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002957 }
2958 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002959 }
2960 }
2961
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002962 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2963 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002965 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002966 in->device = val;
2967 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002968 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002969 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002970 }
2971 }
2972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002973 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002974 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002975
2976 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302977error:
Eric Laurent994a6932013-07-17 11:51:42 -07002978 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002979 return ret;
2980}
2981
2982static char* in_get_parameters(const struct audio_stream *stream,
2983 const char *keys)
2984{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002985 struct stream_in *in = (struct stream_in *)stream;
2986 struct str_parms *query = str_parms_create_str(keys);
2987 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002988 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002989
2990 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002991 if (reply) {
2992 str_parms_destroy(reply);
2993 }
2994 if (query) {
2995 str_parms_destroy(query);
2996 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002997 ALOGE("in_get_parameters: failed to create query or reply");
2998 return NULL;
2999 }
3000
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003001 ALOGV("%s: enter: keys - %s", __func__, keys);
3002
3003 voice_extn_in_get_parameters(in, query, reply);
3004
3005 str = str_parms_to_str(reply);
3006 str_parms_destroy(query);
3007 str_parms_destroy(reply);
3008
3009 ALOGV("%s: exit: returns - %s", __func__, str);
3010 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003011}
3012
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003013static int in_set_gain(struct audio_stream_in *stream __unused,
3014 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015{
3016 return 0;
3017}
3018
3019static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3020 size_t bytes)
3021{
3022 struct stream_in *in = (struct stream_in *)stream;
3023 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303024 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303025 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003027 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303028
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003029 if (in->is_st_session) {
3030 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3031 /* Read from sound trigger HAL */
3032 audio_extn_sound_trigger_read(in, buffer, bytes);
3033 pthread_mutex_unlock(&in->lock);
3034 return bytes;
3035 }
3036
Ashish Jainbbce4322016-02-16 13:25:27 +05303037 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003038 ALOGD(" %s: sound card is not active/SSR state", __func__);
3039 ret= -EIO;;
3040 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303041 }
3042
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003044 pthread_mutex_lock(&adev->lock);
3045 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3046 ret = voice_extn_compress_voip_start_input_stream(in);
3047 else
3048 ret = start_input_stream(in);
3049 pthread_mutex_unlock(&adev->lock);
3050 if (ret != 0) {
3051 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052 }
3053 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003054 if (adev->adm_register_input_stream)
3055 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003058 if (adev->adm_request_focus)
3059 adev->adm_request_focus(adev->adm_data, in->capture_handle);
3060
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003061 if (in->pcm) {
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003062 if (audio_extn_ssr_get_stream() == in)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003063 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07003064 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
3065 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003066 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
3067 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003068 else
3069 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303070 if (ret < 0)
3071 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003072 }
3073
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003074 if (adev->adm_abandon_focus)
3075 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
3076
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077 /*
3078 * Instead of writing zeroes here, we could trust the hardware
3079 * to always provide zeroes when muted.
3080 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303081 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3082 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083 memset(buffer, 0, bytes);
3084
3085exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303086 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303087 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003088 if (-ENETRESET == ret)
3089 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3090
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003091 pthread_mutex_unlock(&in->lock);
3092
3093 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303094 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303095 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303096 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303097 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303098 in->standby = true;
3099 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303100 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003102 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303103 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303104 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105 }
3106 return bytes;
3107}
3108
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003109static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110{
3111 return 0;
3112}
3113
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003114static int add_remove_audio_effect(const struct audio_stream *stream,
3115 effect_handle_t effect,
3116 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003118 struct stream_in *in = (struct stream_in *)stream;
3119 int status = 0;
3120 effect_descriptor_t desc;
3121
3122 status = (*effect)->get_descriptor(effect, &desc);
3123 if (status != 0)
3124 return status;
3125
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003126 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003127 pthread_mutex_lock(&in->dev->lock);
3128 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3129 in->enable_aec != enable &&
3130 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3131 in->enable_aec = enable;
3132 if (!in->standby)
3133 select_devices(in->dev, in->usecase);
3134 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003135 if (in->enable_ns != enable &&
3136 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3137 in->enable_ns = enable;
3138 if (!in->standby)
3139 select_devices(in->dev, in->usecase);
3140 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003141 pthread_mutex_unlock(&in->dev->lock);
3142 pthread_mutex_unlock(&in->lock);
3143
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 return 0;
3145}
3146
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003147static int in_add_audio_effect(const struct audio_stream *stream,
3148 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149{
Eric Laurent994a6932013-07-17 11:51:42 -07003150 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003151 return add_remove_audio_effect(stream, effect, true);
3152}
3153
3154static int in_remove_audio_effect(const struct audio_stream *stream,
3155 effect_handle_t effect)
3156{
Eric Laurent994a6932013-07-17 11:51:42 -07003157 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003158 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159}
3160
3161static int adev_open_output_stream(struct audio_hw_device *dev,
3162 audio_io_handle_t handle,
3163 audio_devices_t devices,
3164 audio_output_flags_t flags,
3165 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003166 struct audio_stream_out **stream_out,
3167 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168{
3169 struct audio_device *adev = (struct audio_device *)dev;
3170 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303171 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003172 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003173
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303175
3176 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3177 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003178 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303179 return -EINVAL;
3180 }
3181
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3183
Mingming Yin3a941d42016-02-17 18:08:05 -08003184 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3185 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303186 devices, flags, &out->stream);
3187
3188
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003189 if (!out) {
3190 return -ENOMEM;
3191 }
3192
Haynes Mathew George204045b2015-02-25 20:32:03 -08003193 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003194 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003195 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3196
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197 if (devices == AUDIO_DEVICE_NONE)
3198 devices = AUDIO_DEVICE_OUT_SPEAKER;
3199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003200 out->flags = flags;
3201 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003202 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003203 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003204 out->sample_rate = config->sample_rate;
3205 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3206 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003207 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003208 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003209 out->non_blocking = 0;
3210 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211
Mingming Yin3a941d42016-02-17 18:08:05 -08003212 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3213 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3214 pthread_mutex_lock(&adev->lock);
3215 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3216 ret = read_hdmi_sink_caps(out);
3217 pthread_mutex_unlock(&adev->lock);
3218 if (ret != 0) {
3219 if (ret == -ENOSYS) {
3220 /* ignore and go with default */
3221 ret = 0;
3222 } else {
3223 ALOGE("error reading hdmi sink caps");
3224 goto error_open;
3225 }
3226 }
3227 }
3228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003229 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003230 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303231 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3232 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003233 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3234 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3235
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003236 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003237 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3238 /*
3239 * Do not handle stereo output in Multi-channel cases
3240 * Stereo case is handled in normal playback path
3241 */
3242 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3243 ret = AUDIO_CHANNEL_OUT_STEREO;
3244 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003245
3246 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3247 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003248 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003249 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003250 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003251
3252 if (config->sample_rate == 0)
3253 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3254 if (config->channel_mask == 0)
3255 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003256 if (config->format == 0)
3257 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003258
3259 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003260 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003261 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3263 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003264 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003265 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003266 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003267 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3268 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003269 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003270 ret = voice_extn_compress_voip_open_output_stream(out);
3271 if (ret != 0) {
3272 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3273 __func__, ret);
3274 goto error_open;
3275 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003276 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3277 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3278
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003279 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3280 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3281 ALOGE("%s: Unsupported Offload information", __func__);
3282 ret = -EINVAL;
3283 goto error_open;
3284 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003285
Mingming Yin3a941d42016-02-17 18:08:05 -08003286 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003287 if(config->offload_info.format == 0)
3288 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003289 if (config->offload_info.sample_rate == 0)
3290 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003291 }
3292
Mingming Yin90310102013-11-13 16:57:00 -08003293 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003294 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003295 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003296 ret = -EINVAL;
3297 goto error_open;
3298 }
3299
3300 out->compr_config.codec = (struct snd_codec *)
3301 calloc(1, sizeof(struct snd_codec));
3302
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003303 if (!out->compr_config.codec) {
3304 ret = -ENOMEM;
3305 goto error_open;
3306 }
3307
vivek mehta0ea887a2015-08-26 14:01:20 -07003308 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003309 out->usecase = get_offload_usecase(adev, true);
3310 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003311 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003312 out->stream.set_callback = out_set_callback;
3313 out->stream.pause = out_pause;
3314 out->stream.resume = out_resume;
3315 out->stream.drain = out_drain;
3316 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003317 out->usecase = get_offload_usecase(adev, false);
3318 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003319 }
vivek mehta446c3962015-09-14 10:57:35 -07003320
3321 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003322 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3323 config->format == 0 && config->sample_rate == 0 &&
3324 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003325 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003326 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3327 } else {
3328 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3329 ret = -EEXIST;
3330 goto error_open;
3331 }
vivek mehta446c3962015-09-14 10:57:35 -07003332 }
3333
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003334 if (config->offload_info.channel_mask)
3335 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003336 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003337 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003338 config->offload_info.channel_mask = config->channel_mask;
3339 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003340 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003341 out->sample_rate = config->offload_info.sample_rate;
3342
Mingming Yin3ee55c62014-08-04 14:23:35 -07003343 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003344
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003345 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003346 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003347 audio_extn_dolby_get_snd_codec_id(adev, out,
3348 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003349 else
3350 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003351 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003352
3353 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3354 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003355 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003356 platform_get_pcm_offload_buffer_size(&config->offload_info);
Mingming Yin21854652016-04-13 11:54:02 -07003357 } else if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003358 out->compr_config.fragment_size =
3359 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003360 } else {
3361 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003362 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003363 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003364 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3365 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003366 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003367 out->compr_config.codec->bit_rate =
3368 config->offload_info.bit_rate;
3369 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003370 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003371 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303372 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003373 /*TODO: Do we need to change it for passthrough */
3374 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003375
Manish Dewangana6fc5442015-08-24 20:30:31 +05303376 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3377 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3378 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3379 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003380 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3381 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003382 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003383 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003384 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3385 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003386
Mingming Yin3ee55c62014-08-04 14:23:35 -07003387 if (out->bit_width == 24) {
3388 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3389 }
3390
Amit Shekhar6f461b12014-08-01 14:52:58 -07003391 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303392 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003393
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003394 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3395 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003396
Mingming Yin497419f2015-07-01 16:57:32 -07003397 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003398 //this flag is set from framework only if its for PCM formats
3399 //no need to check for PCM format again
3400 out->non_blocking = 0;
3401 out->use_small_bufs = true;
3402 ALOGI("Keep write blocking for small buff: non_blockling %d",
3403 out->non_blocking);
3404 }
3405
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003406 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303407 out->send_next_track_params = false;
3408 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003409 out->offload_state = OFFLOAD_STATE_IDLE;
3410 out->playback_started = 0;
3411
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003412 audio_extn_dts_create_state_notifier_node(out->usecase);
3413
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003414 create_offload_callback_thread(out);
3415 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3416 __func__, config->offload_info.version,
3417 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003418 //Decide if we need to use gapless mode by default
Mingming Yin21854652016-04-13 11:54:02 -07003419 if (!audio_extn_dolby_is_passthrough_stream(out)) {
3420 ALOGV("%s: don't enable gapless for passthrough", __func__);
3421 check_and_set_gapless_mode(adev);
3422 }
3423
3424 if (audio_extn_dolby_is_passthrough_stream(out)) {
3425 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3426 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003427 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303428 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003429 if (ret != 0) {
3430 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3431 __func__, ret);
3432 goto error_open;
3433 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003434 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3435 if (config->sample_rate == 0)
3436 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3437 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3438 config->sample_rate != 8000) {
3439 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3440 ret = -EINVAL;
3441 goto error_open;
3442 }
3443 out->sample_rate = config->sample_rate;
3444 out->config.rate = config->sample_rate;
3445 if (config->format == AUDIO_FORMAT_DEFAULT)
3446 config->format = AUDIO_FORMAT_PCM_16_BIT;
3447 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3448 config->format = AUDIO_FORMAT_PCM_16_BIT;
3449 ret = -EINVAL;
3450 goto error_open;
3451 }
3452 out->format = config->format;
3453 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3454 out->config = pcm_config_afe_proxy_playback;
3455 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003456 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3457 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3458 out->config = pcm_config_low_latency;
3459 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003460 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003461 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003462 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3463 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003464 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003465 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3466 format = AUDIO_FORMAT_PCM_16_BIT;
3467 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3468 out->config = pcm_config_deep_buffer;
3469 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003470 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003471 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003472 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003473 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003474 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003475 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476 }
3477
Mingming Yin21854652016-04-13 11:54:02 -07003478 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d out->flags:%x, flags:%x",
3479 __func__, devices, flags, format, out->sample_rate, out->bit_width, out->flags, flags);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003480 /* TODO remove this hardcoding and check why width is zero*/
3481 if (out->bit_width == 0)
3482 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003483 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3484 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003485 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303486 out->bit_width, out->channel_mask,
3487 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003488 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3489 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3490 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003491 if(adev->primary_output == NULL)
3492 adev->primary_output = out;
3493 else {
3494 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003495 ret = -EEXIST;
3496 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003497 }
3498 }
3499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003500 /* Check if this usecase is already existing */
3501 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003502 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3503 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003506 ret = -EEXIST;
3507 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508 }
3509 pthread_mutex_unlock(&adev->lock);
3510
3511 out->stream.common.get_sample_rate = out_get_sample_rate;
3512 out->stream.common.set_sample_rate = out_set_sample_rate;
3513 out->stream.common.get_buffer_size = out_get_buffer_size;
3514 out->stream.common.get_channels = out_get_channels;
3515 out->stream.common.get_format = out_get_format;
3516 out->stream.common.set_format = out_set_format;
3517 out->stream.common.standby = out_standby;
3518 out->stream.common.dump = out_dump;
3519 out->stream.common.set_parameters = out_set_parameters;
3520 out->stream.common.get_parameters = out_get_parameters;
3521 out->stream.common.add_audio_effect = out_add_audio_effect;
3522 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3523 out->stream.get_latency = out_get_latency;
3524 out->stream.set_volume = out_set_volume;
3525 out->stream.write = out_write;
3526 out->stream.get_render_position = out_get_render_position;
3527 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003528 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003531 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003532 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533
3534 config->format = out->stream.common.get_format(&out->stream.common);
3535 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3536 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3537
3538 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303539 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003540 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003541
3542 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3543 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3544 popcount(out->channel_mask), out->playback_started);
3545
Eric Laurent994a6932013-07-17 11:51:42 -07003546 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003548
3549error_open:
3550 free(out);
3551 *stream_out = NULL;
3552 ALOGD("%s: exit: ret %d", __func__, ret);
3553 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554}
3555
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003556static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557 struct audio_stream_out *stream)
3558{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003559 struct stream_out *out = (struct stream_out *)stream;
3560 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003561 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003562
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303563 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3564
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003565 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303566 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003567 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303568 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003569 if(ret != 0)
3570 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3571 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003572 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003573 out_standby(&stream->common);
3574
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003575 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003576 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003577 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003578 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003579 if (out->compr_config.codec != NULL)
3580 free(out->compr_config.codec);
3581 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003582
3583 if (adev->voice_tx_output == out)
3584 adev->voice_tx_output = NULL;
3585
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003586 pthread_cond_destroy(&out->cond);
3587 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003588 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003589 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590}
3591
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003592static void close_compress_sessions(struct audio_device *adev)
3593{
Mingming Yin7b762e72015-03-04 13:47:32 -08003594 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303595 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003596 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003597 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303598
3599 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003600 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303601 if (is_offload_usecase(usecase->id)) {
3602 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003603 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3604 out = usecase->stream.out;
3605 pthread_mutex_unlock(&adev->lock);
3606 out_standby(&out->stream.common);
3607 pthread_mutex_lock(&adev->lock);
3608 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303609 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003610 }
3611 pthread_mutex_unlock(&adev->lock);
3612}
3613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3615{
3616 struct audio_device *adev = (struct audio_device *)dev;
3617 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003618 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003619 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003620 int ret;
3621 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003623 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303626 if (!parms)
3627 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003628 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3629 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303630 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303631 if (strstr(snd_card_status, "OFFLINE")) {
3632 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303633 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003634 //close compress sessions on OFFLINE status
3635 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303636 } else if (strstr(snd_card_status, "ONLINE")) {
3637 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303638 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003639 //send dts hpx license if enabled
3640 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303641 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303642 }
3643
3644 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003645 status = voice_set_parameters(adev, parms);
3646 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003647 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003649 status = platform_set_parameters(adev->platform, parms);
3650 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003651 goto done;
3652
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003653 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3654 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003655 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3657 adev->bluetooth_nrec = true;
3658 else
3659 adev->bluetooth_nrec = false;
3660 }
3661
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003662 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3663 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3665 adev->screen_off = false;
3666 else
3667 adev->screen_off = true;
3668 }
3669
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003670 ret = str_parms_get_int(parms, "rotation", &val);
3671 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003672 bool reverse_speakers = false;
3673 switch(val) {
3674 // FIXME: note that the code below assumes that the speakers are in the correct placement
3675 // relative to the user when the device is rotated 90deg from its default rotation. This
3676 // assumption is device-specific, not platform-specific like this code.
3677 case 270:
3678 reverse_speakers = true;
3679 break;
3680 case 0:
3681 case 90:
3682 case 180:
3683 break;
3684 default:
3685 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003686 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003687 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003688 if (status == 0) {
3689 if (adev->speaker_lr_swap != reverse_speakers) {
3690 adev->speaker_lr_swap = reverse_speakers;
3691 // only update the selected device if there is active pcm playback
3692 struct audio_usecase *usecase;
3693 struct listnode *node;
3694 list_for_each(node, &adev->usecase_list) {
3695 usecase = node_to_item(node, struct audio_usecase, list);
3696 if (usecase->type == PCM_PLAYBACK) {
3697 select_devices(adev, usecase->id);
3698 break;
3699 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003700 }
3701 }
3702 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003703 }
3704
Mingming Yin514a8bc2014-07-29 15:22:21 -07003705 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3706 if (ret >= 0) {
3707 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3708 adev->bt_wb_speech_enabled = true;
3709 else
3710 adev->bt_wb_speech_enabled = false;
3711 }
3712
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003713 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3714 if (ret >= 0) {
3715 val = atoi(value);
3716 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3717 ALOGV("cache new edid");
3718 platform_cache_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003719 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3720 /*
3721 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
3722 * Per AudioPolicyManager, USB device is higher priority than WFD.
3723 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
3724 * If WFD use case occupies AFE proxy, it may result unintended behavior while
3725 * starting voice call on USB
3726 */
3727 ALOGV("detected USB connect .. disable proxy");
3728 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003729 }
3730 }
3731
3732 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3733 if (ret >= 0) {
3734 val = atoi(value);
3735 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3736 ALOGV("invalidate cached edid");
3737 platform_invalidate_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003738 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3739 ALOGV("detected USB disconnect .. enable proxy");
3740 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003741 }
3742 }
3743
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003744 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003745
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003746done:
3747 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003748 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303749error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003750 ALOGV("%s: exit with code(%d)", __func__, status);
3751 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003752}
3753
3754static char* adev_get_parameters(const struct audio_hw_device *dev,
3755 const char *keys)
3756{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003757 struct audio_device *adev = (struct audio_device *)dev;
3758 struct str_parms *reply = str_parms_create();
3759 struct str_parms *query = str_parms_create_str(keys);
3760 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303761 char value[256] = {0};
3762 int ret = 0;
3763
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003764 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003765 if (reply) {
3766 str_parms_destroy(reply);
3767 }
3768 if (query) {
3769 str_parms_destroy(query);
3770 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003771 ALOGE("adev_get_parameters: failed to create query or reply");
3772 return NULL;
3773 }
3774
Naresh Tannirud7205b62014-06-20 02:54:48 +05303775 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3776 sizeof(value));
3777 if (ret >=0) {
3778 int val = 1;
3779 pthread_mutex_lock(&adev->snd_card_status.lock);
3780 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3781 val = 0;
3782 pthread_mutex_unlock(&adev->snd_card_status.lock);
3783 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3784 goto exit;
3785 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003786
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003787 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003788 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003789 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003790 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303791 pthread_mutex_unlock(&adev->lock);
3792
Naresh Tannirud7205b62014-06-20 02:54:48 +05303793exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003794 str = str_parms_to_str(reply);
3795 str_parms_destroy(query);
3796 str_parms_destroy(reply);
3797
3798 ALOGV("%s: exit: returns - %s", __func__, str);
3799 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003800}
3801
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003802static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803{
3804 return 0;
3805}
3806
3807static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3808{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003809 int ret;
3810 struct audio_device *adev = (struct audio_device *)dev;
3811 pthread_mutex_lock(&adev->lock);
3812 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003813 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003814 pthread_mutex_unlock(&adev->lock);
3815 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816}
3817
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003818static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3819 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003820{
3821 return -ENOSYS;
3822}
3823
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003824static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3825 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003826{
3827 return -ENOSYS;
3828}
3829
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003830static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3831 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003832{
3833 return -ENOSYS;
3834}
3835
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003836static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3837 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838{
3839 return -ENOSYS;
3840}
3841
3842static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3843{
3844 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003845
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003846 pthread_mutex_lock(&adev->lock);
3847 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003848 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003850 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003851 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003852 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003853 adev->current_call_output = NULL;
3854 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003855 }
3856 pthread_mutex_unlock(&adev->lock);
3857 return 0;
3858}
3859
3860static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3861{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003862 int ret;
3863
3864 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003865 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003866 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3867 pthread_mutex_unlock(&adev->lock);
3868
3869 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870}
3871
3872static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3873{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003874 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003875 return 0;
3876}
3877
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003878static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003879 const struct audio_config *config)
3880{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003881 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003882
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003883 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3884 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003885}
3886
3887static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003888 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889 audio_devices_t devices,
3890 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003891 struct audio_stream_in **stream_in,
3892 audio_input_flags_t flags __unused,
3893 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003894 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003895{
3896 struct audio_device *adev = (struct audio_device *)dev;
3897 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003898 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003899 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003900 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303901
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003902 *stream_in = NULL;
3903 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3904 return -EINVAL;
3905
3906 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003907
3908 if (!in) {
3909 ALOGE("failed to allocate input stream");
3910 return -ENOMEM;
3911 }
3912
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303913 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003914 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3915 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003916
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003917 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003918 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003920 in->stream.common.get_sample_rate = in_get_sample_rate;
3921 in->stream.common.set_sample_rate = in_set_sample_rate;
3922 in->stream.common.get_buffer_size = in_get_buffer_size;
3923 in->stream.common.get_channels = in_get_channels;
3924 in->stream.common.get_format = in_get_format;
3925 in->stream.common.set_format = in_set_format;
3926 in->stream.common.standby = in_standby;
3927 in->stream.common.dump = in_dump;
3928 in->stream.common.set_parameters = in_set_parameters;
3929 in->stream.common.get_parameters = in_get_parameters;
3930 in->stream.common.add_audio_effect = in_add_audio_effect;
3931 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3932 in->stream.set_gain = in_set_gain;
3933 in->stream.read = in_read;
3934 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3935
3936 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003937 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003938 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003939 in->standby = 1;
3940 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003941 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003942 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003943
3944 /* Update config params with the requested sample rate and channels */
3945 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003946 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3947 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3948 is_low_latency = true;
3949#if LOW_LATENCY_CAPTURE_USE_CASE
3950 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3951#endif
3952 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003953 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003955 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003956
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003957 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303958 if (adev->mode != AUDIO_MODE_IN_CALL) {
3959 ret = -EINVAL;
3960 goto err_open;
3961 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003962 if (config->sample_rate == 0)
3963 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3964 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3965 config->sample_rate != 8000) {
3966 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3967 ret = -EINVAL;
3968 goto err_open;
3969 }
3970 if (config->format == AUDIO_FORMAT_DEFAULT)
3971 config->format = AUDIO_FORMAT_PCM_16_BIT;
3972 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3973 config->format = AUDIO_FORMAT_PCM_16_BIT;
3974 ret = -EINVAL;
3975 goto err_open;
3976 }
3977
3978 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3979 in->config = pcm_config_afe_proxy_record;
3980 in->config.channels = channel_count;
3981 in->config.rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05303982 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
3983 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07003984 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003985 audio_extn_compr_cap_format_supported(config->format) &&
3986 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003987 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003988 } else {
3989 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003990 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003991 buffer_size = get_input_buffer_size(config->sample_rate,
3992 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003993 channel_count,
3994 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003995 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003996 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3997 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3998 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003999 (in->config.rate == 8000 || in->config.rate == 16000 ||
4000 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004001 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4002 voice_extn_compress_voip_open_input_stream(in);
4003 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004004 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004005
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004006 /* This stream could be for sound trigger lab,
4007 get sound trigger pcm if present */
4008 audio_extn_sound_trigger_check_and_get_session(in);
4009
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004010 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004011 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004012 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004013
4014err_open:
4015 free(in);
4016 *stream_in = NULL;
4017 return ret;
4018}
4019
4020static void adev_close_input_stream(struct audio_hw_device *dev,
4021 struct audio_stream_in *stream)
4022{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004023 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004024 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004025 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304026
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304027 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004028
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304029 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004030 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304031
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004032 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304033 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004034 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304035 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004036 if (ret != 0)
4037 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4038 __func__, ret);
4039 } else
4040 in_standby(&stream->common);
4041
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004042 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004043 audio_extn_ssr_deinit();
4044 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004045
Mingming Yine62d7842013-10-25 16:26:03 -07004046 if(audio_extn_compr_cap_enabled() &&
4047 audio_extn_compr_cap_format_supported(in->config.format))
4048 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004049
Mingming Yinfd7607b2016-01-22 12:48:44 -08004050 if (in->is_st_session) {
4051 ALOGV("%s: sound trigger pcm stop lab", __func__);
4052 audio_extn_sound_trigger_stop_lab(in);
4053 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004054 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055 return;
4056}
4057
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004058static int adev_dump(const audio_hw_device_t *device __unused,
4059 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060{
4061 return 0;
4062}
4063
4064static int adev_close(hw_device_t *device)
4065{
4066 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004067
4068 if (!adev)
4069 return 0;
4070
4071 pthread_mutex_lock(&adev_init_lock);
4072
4073 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004074 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004075 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004076 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004077 audio_route_free(adev->audio_route);
4078 free(adev->snd_dev_ref_cnt);
4079 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004080 if (adev->adm_deinit)
4081 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004082 free(device);
4083 adev = NULL;
4084 }
4085 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004086
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087 return 0;
4088}
4089
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004090/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4091 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4092 * just that it _might_ work.
4093 */
4094static int period_size_is_plausible_for_low_latency(int period_size)
4095{
4096 switch (period_size) {
4097 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004098 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004099 case 240:
4100 case 320:
4101 case 480:
4102 return 1;
4103 default:
4104 return 0;
4105 }
4106}
4107
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004108static int adev_open(const hw_module_t *module, const char *name,
4109 hw_device_t **device)
4110{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004111 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004112 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4113
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004114 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004115 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004116 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004117 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004118 ALOGD("%s: returning existing instance of adev", __func__);
4119 ALOGD("%s: exit", __func__);
4120 pthread_mutex_unlock(&adev_init_lock);
4121 return 0;
4122 }
4123
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004124 adev = calloc(1, sizeof(struct audio_device));
4125
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004126 if (!adev) {
4127 pthread_mutex_unlock(&adev_init_lock);
4128 return -ENOMEM;
4129 }
4130
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004131 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4132
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004133 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4134 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4135 adev->device.common.module = (struct hw_module_t *)module;
4136 adev->device.common.close = adev_close;
4137
4138 adev->device.init_check = adev_init_check;
4139 adev->device.set_voice_volume = adev_set_voice_volume;
4140 adev->device.set_master_volume = adev_set_master_volume;
4141 adev->device.get_master_volume = adev_get_master_volume;
4142 adev->device.set_master_mute = adev_set_master_mute;
4143 adev->device.get_master_mute = adev_get_master_mute;
4144 adev->device.set_mode = adev_set_mode;
4145 adev->device.set_mic_mute = adev_set_mic_mute;
4146 adev->device.get_mic_mute = adev_get_mic_mute;
4147 adev->device.set_parameters = adev_set_parameters;
4148 adev->device.get_parameters = adev_get_parameters;
4149 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4150 adev->device.open_output_stream = adev_open_output_stream;
4151 adev->device.close_output_stream = adev_close_output_stream;
4152 adev->device.open_input_stream = adev_open_input_stream;
4153 adev->device.close_input_stream = adev_close_input_stream;
4154 adev->device.dump = adev_dump;
4155
4156 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004157 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004158 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004159 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004160 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004162 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004163 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004164 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004165 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004166 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004167 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004168 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004169 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304170 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304171 adev->perf_lock_opts[0] = 0x101;
4172 adev->perf_lock_opts[1] = 0x20E;
4173 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304174
4175 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4176 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004177 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004178 adev->platform = platform_init(adev);
4179 if (!adev->platform) {
4180 free(adev->snd_dev_ref_cnt);
4181 free(adev);
4182 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4183 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004184 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004185 return -EINVAL;
4186 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004187
Naresh Tanniru4c630392014-05-12 01:05:52 +05304188 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4189
Eric Laurentc4aef752013-09-12 17:45:53 -07004190 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4191 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4192 if (adev->visualizer_lib == NULL) {
4193 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4194 } else {
4195 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4196 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004197 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004198 "visualizer_hal_start_output");
4199 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004200 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004201 "visualizer_hal_stop_output");
4202 }
4203 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004204 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004205 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004206
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004207 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4208 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4209 if (adev->offload_effects_lib == NULL) {
4210 ALOGE("%s: DLOPEN failed for %s", __func__,
4211 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4212 } else {
4213 ALOGV("%s: DLOPEN successful for %s", __func__,
4214 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4215 adev->offload_effects_start_output =
4216 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4217 "offload_effects_bundle_hal_start_output");
4218 adev->offload_effects_stop_output =
4219 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4220 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004221 adev->offload_effects_set_hpx_state =
4222 (int (*)(bool))dlsym(adev->offload_effects_lib,
4223 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304224 adev->offload_effects_get_parameters =
4225 (void (*)(struct str_parms *, struct str_parms *))
4226 dlsym(adev->offload_effects_lib,
4227 "offload_effects_bundle_get_parameters");
4228 adev->offload_effects_set_parameters =
4229 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4230 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004231 }
4232 }
4233
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004234 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4235 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4236 if (adev->adm_lib == NULL) {
4237 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4238 } else {
4239 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4240 adev->adm_init = (adm_init_t)
4241 dlsym(adev->adm_lib, "adm_init");
4242 adev->adm_deinit = (adm_deinit_t)
4243 dlsym(adev->adm_lib, "adm_deinit");
4244 adev->adm_register_input_stream = (adm_register_input_stream_t)
4245 dlsym(adev->adm_lib, "adm_register_input_stream");
4246 adev->adm_register_output_stream = (adm_register_output_stream_t)
4247 dlsym(adev->adm_lib, "adm_register_output_stream");
4248 adev->adm_deregister_stream = (adm_deregister_stream_t)
4249 dlsym(adev->adm_lib, "adm_deregister_stream");
4250 adev->adm_request_focus = (adm_request_focus_t)
4251 dlsym(adev->adm_lib, "adm_request_focus");
4252 adev->adm_abandon_focus = (adm_abandon_focus_t)
4253 dlsym(adev->adm_lib, "adm_abandon_focus");
4254 }
4255 }
4256
Mingming Yin514a8bc2014-07-29 15:22:21 -07004257 adev->bt_wb_speech_enabled = false;
4258
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004259 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004260 *device = &adev->device.common;
4261
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004262 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4263 &adev->streams_output_cfg_list);
4264
Kiran Kandi910e1862013-10-29 13:29:42 -07004265 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004266
4267 char value[PROPERTY_VALUE_MAX];
4268 int trial;
4269 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4270 trial = atoi(value);
4271 if (period_size_is_plausible_for_low_latency(trial)) {
4272 pcm_config_low_latency.period_size = trial;
4273 pcm_config_low_latency.start_threshold = trial / 4;
4274 pcm_config_low_latency.avail_min = trial / 4;
4275 configured_low_latency_capture_period_size = trial;
4276 }
4277 }
4278 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4279 trial = atoi(value);
4280 if (period_size_is_plausible_for_low_latency(trial)) {
4281 configured_low_latency_capture_period_size = trial;
4282 }
4283 }
4284
vivek mehta446c3962015-09-14 10:57:35 -07004285 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004286 pthread_mutex_unlock(&adev_init_lock);
4287
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004288 if (adev->adm_init)
4289 adev->adm_data = adev->adm_init();
4290
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304291 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004292 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004293 return 0;
4294}
4295
4296static struct hw_module_methods_t hal_module_methods = {
4297 .open = adev_open,
4298};
4299
4300struct audio_module HAL_MODULE_INFO_SYM = {
4301 .common = {
4302 .tag = HARDWARE_MODULE_TAG,
4303 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4304 .hal_api_version = HARDWARE_HAL_API_VERSION,
4305 .id = AUDIO_HARDWARE_MODULE_ID,
4306 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004307 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004308 .methods = &hal_module_methods,
4309 },
4310};