blob: b92d809103ec76fecce153cf81219605786ef687 [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;
Mingming Yin9c041392014-05-01 15:37:31 -07001826 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001827 struct audio_usecase *uc_info;
1828 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301829 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001831 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1832 ret = -EINVAL;
1833 goto error_config;
1834 }
1835
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301836 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1837 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1838 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301839
Naresh Tanniru80659832014-06-04 18:17:56 +05301840 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301841 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301842 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301843 goto error_config;
1844 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301845
Eric Laurentb23d5282013-05-14 15:27:20 -07001846 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847 if (out->pcm_device_id < 0) {
1848 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1849 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001850 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001851 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852 }
1853
1854 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001855
1856 if (!uc_info) {
1857 ret = -ENOMEM;
1858 goto error_config;
1859 }
1860
Mingming Yin21854652016-04-13 11:54:02 -07001861 /* This must be called before adding this usecase to the list */
1862 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1863 /* This call can fail if compress pass thru is already active */
1864 check_and_set_hdmi_backend(out);
1865 }
1866
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867 uc_info->id = out->usecase;
1868 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001869 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001870 uc_info->devices = out->devices;
1871 uc_info->in_snd_device = SND_DEVICE_NONE;
1872 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001873 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301875 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1876 adev->perf_lock_opts,
1877 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001878 select_devices(adev, out->usecase);
1879
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001880 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1881 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001882 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001883 unsigned int flags = PCM_OUT;
1884 unsigned int pcm_open_retry_count = 0;
1885 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1886 flags |= PCM_MMAP | PCM_NOIRQ;
1887 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1888 } else
1889 flags |= PCM_MONOTONIC;
1890
1891 while (1) {
1892 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1893 flags, &out->config);
1894 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1895 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1896 if (out->pcm != NULL) {
1897 pcm_close(out->pcm);
1898 out->pcm = NULL;
1899 }
1900 if (pcm_open_retry_count-- == 0) {
1901 ret = -EIO;
1902 goto error_open;
1903 }
1904 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1905 continue;
1906 }
1907 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001908 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001909
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001910 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1911 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001912
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001913 ALOGV("%s: pcm_prepare", __func__);
1914 if (pcm_is_ready(out->pcm)) {
1915 ret = pcm_prepare(out->pcm);
1916 if (ret < 0) {
1917 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1918 pcm_close(out->pcm);
1919 out->pcm = NULL;
1920 goto error_open;
1921 }
1922 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001923 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001924 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1925 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001927 out->compr = compress_open(adev->snd_card,
1928 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001929 COMPRESS_IN, &out->compr_config);
1930 if (out->compr && !is_compress_ready(out->compr)) {
1931 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1932 compress_close(out->compr);
1933 out->compr = NULL;
1934 ret = -EIO;
1935 goto error_open;
1936 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301937 /* compress_open sends params of the track, so reset the flag here */
1938 out->is_compr_metadata_avail = false;
1939
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001940 if (out->offload_callback)
1941 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001942
Fred Oh3f43e742015-03-04 18:42:34 -08001943 /* Since small bufs uses blocking writes, a write will be blocked
1944 for the default max poll time (20s) in the event of an SSR.
1945 Reduce the poll time to observe and deal with SSR faster.
1946 */
1947 if (out->use_small_bufs) {
1948 compress_set_max_poll_wait(out->compr, 1000);
1949 }
1950
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001951 audio_extn_dts_create_state_notifier_node(out->usecase);
1952 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1953 popcount(out->channel_mask),
1954 out->playback_started);
1955
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001956#ifdef DS1_DOLBY_DDP_ENABLED
1957 if (audio_extn_is_dolby_format(out->format))
1958 audio_extn_dolby_send_ddp_endp_params(adev);
1959#endif
Mingming Yin21854652016-04-13 11:54:02 -07001960 if (!(audio_extn_dolby_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001961 if (adev->visualizer_start_output != NULL)
1962 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1963 if (adev->offload_effects_start_output != NULL)
1964 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001965 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001966 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301968 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001969 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001971 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001972error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301973 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001975error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301976 /*
1977 * sleep 50ms to allow sufficient time for kernel
1978 * drivers to recover incases like SSR.
1979 */
1980 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001981 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982}
1983
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984static int check_input_parameters(uint32_t sample_rate,
1985 audio_format_t format,
1986 int channel_count)
1987{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001988 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001990 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001991 !voice_extn_compress_voip_is_format_supported(format) &&
1992 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001993
1994 switch (channel_count) {
1995 case 1:
1996 case 2:
1997 case 6:
1998 break;
1999 default:
2000 ret = -EINVAL;
2001 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002
2003 switch (sample_rate) {
2004 case 8000:
2005 case 11025:
2006 case 12000:
2007 case 16000:
2008 case 22050:
2009 case 24000:
2010 case 32000:
2011 case 44100:
2012 case 48000:
2013 break;
2014 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002015 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016 }
2017
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002018 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019}
2020
2021static size_t get_input_buffer_size(uint32_t sample_rate,
2022 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002023 int channel_count,
2024 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002025{
2026 size_t size = 0;
2027
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002028 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2029 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002031 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002032 if (is_low_latency)
2033 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002034 /* ToDo: should use frame_size computed based on the format and
2035 channel_count here. */
2036 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002038 /* make sure the size is multiple of 32 bytes
2039 * At 48 kHz mono 16-bit PCM:
2040 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2041 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2042 */
2043 size += 0x1f;
2044 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002045
2046 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047}
2048
2049static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2050{
2051 struct stream_out *out = (struct stream_out *)stream;
2052
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002053 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054}
2055
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002056static int out_set_sample_rate(struct audio_stream *stream __unused,
2057 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058{
2059 return -ENOSYS;
2060}
2061
2062static size_t out_get_buffer_size(const struct audio_stream *stream)
2063{
2064 struct stream_out *out = (struct stream_out *)stream;
2065
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002066 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002067 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002068 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2069 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002070
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002071 return out->config.period_size *
2072 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002073}
2074
2075static uint32_t out_get_channels(const struct audio_stream *stream)
2076{
2077 struct stream_out *out = (struct stream_out *)stream;
2078
2079 return out->channel_mask;
2080}
2081
2082static audio_format_t out_get_format(const struct audio_stream *stream)
2083{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002084 struct stream_out *out = (struct stream_out *)stream;
2085
2086 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002087}
2088
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002089static int out_set_format(struct audio_stream *stream __unused,
2090 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002091{
2092 return -ENOSYS;
2093}
2094
2095static int out_standby(struct audio_stream *stream)
2096{
2097 struct stream_out *out = (struct stream_out *)stream;
2098 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002099
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302100 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2101 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002102 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2103 /* Ignore standby in case of voip call because the voip output
2104 * stream is closed in adev_close_output_stream()
2105 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302106 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002107 return 0;
2108 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002110 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002111 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002112 if (adev->adm_deregister_stream)
2113 adev->adm_deregister_stream(adev->adm_data, out->handle);
2114
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002115 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002117 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002118 if (out->pcm) {
2119 pcm_close(out->pcm);
2120 out->pcm = NULL;
2121 }
2122 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002123 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002124 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302125 out->send_next_track_params = false;
2126 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002127 out->gapless_mdata.encoder_delay = 0;
2128 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002129 if (out->compr != NULL) {
2130 compress_close(out->compr);
2131 out->compr = NULL;
2132 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002133 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002134 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002135 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002136 }
2137 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302138 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002139 return 0;
2140}
2141
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002142static int out_dump(const struct audio_stream *stream __unused,
2143 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144{
2145 return 0;
2146}
2147
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002148static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2149{
2150 int ret = 0;
2151 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002152
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002153 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002154 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002155 return -EINVAL;
2156 }
2157
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302158 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002159
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002160 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2161 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302162 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002163 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002164 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2165 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302166 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002167 }
2168
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002169 ALOGV("%s new encoder delay %u and padding %u", __func__,
2170 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2171
2172 return 0;
2173}
2174
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002175static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2176{
2177 return out == adev->primary_output || out == adev->voice_tx_output;
2178}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002179
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002180static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2181{
2182 struct stream_out *out = (struct stream_out *)stream;
2183 struct audio_device *adev = out->dev;
2184 struct str_parms *parms;
2185 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002186 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002187
sangwoobc677242013-08-08 16:53:43 +09002188 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002189 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302191 if (!parms)
2192 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002193 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2194 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002196 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002197 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002199 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302200 * When HDMI cable is unplugged/usb hs is disconnected the
2201 * music playback is paused and the policy manager sends routing=0
2202 * But the audioflingercontinues to write data until standby time
2203 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002204 * Avoid this by routing audio to speaker until standby.
2205 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302206 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2207 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002208 val == AUDIO_DEVICE_NONE) {
Mingming Yin21854652016-04-13 11:54:02 -07002209 if (!audio_extn_dolby_is_passthrough_stream(out))
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08002210 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002211 }
2212
2213 /*
2214 * select_devices() call below switches all the usecases on the same
2215 * backend to the new device. Refer to check_usecases_codec_backend() in
2216 * the select_devices(). But how do we undo this?
2217 *
2218 * For example, music playback is active on headset (deep-buffer usecase)
2219 * and if we go to ringtones and select a ringtone, low-latency usecase
2220 * will be started on headset+speaker. As we can't enable headset+speaker
2221 * and headset devices at the same time, select_devices() switches the music
2222 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2223 * So when the ringtone playback is completed, how do we undo the same?
2224 *
2225 * We are relying on the out_set_parameters() call on deep-buffer output,
2226 * once the ringtone playback is ended.
2227 * NOTE: We should not check if the current devices are same as new devices.
2228 * Because select_devices() must be called to switch back the music
2229 * playback to headset.
2230 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002231 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002232 out->devices = val;
2233
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302234 if (!out->standby) {
2235 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2236 adev->perf_lock_opts,
2237 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002238 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302239 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2240 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002241
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002242 if (output_drives_call(adev, out)) {
2243 if(!voice_is_in_call(adev)) {
2244 if (adev->mode == AUDIO_MODE_IN_CALL) {
2245 adev->current_call_output = out;
2246 ret = voice_start_call(adev);
2247 }
2248 } else {
2249 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002250 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002251 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002252 }
2253 }
2254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002256 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002258
2259 if (out == adev->primary_output) {
2260 pthread_mutex_lock(&adev->lock);
2261 audio_extn_set_parameters(adev, parms);
2262 pthread_mutex_unlock(&adev->lock);
2263 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002264 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002265 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002266 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002267
2268 audio_extn_dts_create_state_notifier_node(out->usecase);
2269 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2270 popcount(out->channel_mask),
2271 out->playback_started);
2272
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002273 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002274 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002275
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002276 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302277error:
Eric Laurent994a6932013-07-17 11:51:42 -07002278 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279 return ret;
2280}
2281
2282static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2283{
2284 struct stream_out *out = (struct stream_out *)stream;
2285 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002286 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002287 char value[256];
2288 struct str_parms *reply = str_parms_create();
2289 size_t i, j;
2290 int ret;
2291 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002292
2293 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002294 if (reply) {
2295 str_parms_destroy(reply);
2296 }
2297 if (query) {
2298 str_parms_destroy(query);
2299 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002300 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2301 return NULL;
2302 }
2303
Eric Laurent994a6932013-07-17 11:51:42 -07002304 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2306 if (ret >= 0) {
2307 value[0] = '\0';
2308 i = 0;
2309 while (out->supported_channel_masks[i] != 0) {
2310 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2311 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2312 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002313 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002315 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002316 first = false;
2317 break;
2318 }
2319 }
2320 i++;
2321 }
2322 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2323 str = str_parms_to_str(reply);
2324 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002325 voice_extn_out_get_parameters(out, query, reply);
2326 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002327 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002328 free(str);
2329 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002330 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002331 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002332
Alexy Joseph62142aa2015-11-16 15:10:34 -08002333
2334 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2335 if (ret >= 0) {
2336 value[0] = '\0';
2337 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2338 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302339 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002340 } else {
2341 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302342 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002343 }
2344 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002345 if (str)
2346 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002347 str = str_parms_to_str(reply);
2348 }
2349
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002350 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2351 if (ret >= 0) {
2352 value[0] = '\0';
2353 i = 0;
2354 first = true;
2355 while (out->supported_formats[i] != 0) {
2356 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2357 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2358 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002359 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002360 }
2361 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2362 first = false;
2363 break;
2364 }
2365 }
2366 i++;
2367 }
2368 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002369 if (str)
2370 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002371 str = str_parms_to_str(reply);
2372 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002373
2374 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2375 if (ret >= 0) {
2376 value[0] = '\0';
2377 i = 0;
2378 first = true;
2379 while (out->supported_sample_rates[i] != 0) {
2380 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2381 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2382 if (!first) {
2383 strlcat(value, "|", sizeof(value));
2384 }
2385 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2386 first = false;
2387 break;
2388 }
2389 }
2390 i++;
2391 }
2392 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2393 if (str)
2394 free(str);
2395 str = str_parms_to_str(reply);
2396 }
2397
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002398 str_parms_destroy(query);
2399 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002400 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002401 return str;
2402}
2403
2404static uint32_t out_get_latency(const struct audio_stream_out *stream)
2405{
2406 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002407 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002408
Alexy Josephaa54c872014-12-03 02:46:47 -08002409 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002410 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002411 } else {
2412 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002413 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002414 }
2415
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302416 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002417 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002418}
2419
2420static int out_set_volume(struct audio_stream_out *stream, float left,
2421 float right)
2422{
Eric Laurenta9024de2013-04-04 09:19:12 -07002423 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002424 int volume[2];
2425
Eric Laurenta9024de2013-04-04 09:19:12 -07002426 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2427 /* only take left channel into account: the API is for stereo anyway */
2428 out->muted = (left == 0.0f);
2429 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002430 } else if (is_offload_usecase(out->usecase)) {
Mingming Yin21854652016-04-13 11:54:02 -07002431 if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002432 /*
2433 * Set mute or umute on HDMI passthrough stream.
2434 * Only take left channel into account.
2435 * Mute is 0 and unmute 1
2436 */
2437 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2438 } else {
2439 char mixer_ctl_name[128];
2440 struct audio_device *adev = out->dev;
2441 struct mixer_ctl *ctl;
2442 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002443 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002444
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002445 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2446 "Compress Playback %d Volume", pcm_device_id);
2447 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2448 if (!ctl) {
2449 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2450 __func__, mixer_ctl_name);
2451 return -EINVAL;
2452 }
2453 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2454 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2455 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2456 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002457 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002458 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002459
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460 return -ENOSYS;
2461}
2462
2463static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2464 size_t bytes)
2465{
2466 struct stream_out *out = (struct stream_out *)stream;
2467 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302468 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002469 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002471 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302472
Naresh Tanniru80659832014-06-04 18:17:56 +05302473 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002474
Ashish Jainbbce4322016-02-16 13:25:27 +05302475 if (is_offload_usecase(out->usecase)) {
2476 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302477 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2478 pthread_mutex_unlock(&out->lock);
2479 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302480 } else {
2481 /* increase written size during SSR to avoid mismatch
2482 * with the written frames count in AF
2483 */
2484 out->written += bytes / (out->config.channels * sizeof(short));
2485 ALOGD(" %s: sound card is not active/SSR state", __func__);
2486 ret= -EIO;
2487 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302488 }
2489 }
2490
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002492 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002493 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002494 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2495 ret = voice_extn_compress_voip_start_output_stream(out);
2496 else
2497 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002498 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002499 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002501 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502 goto exit;
2503 }
vivek mehta446c3962015-09-14 10:57:35 -07002504 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002505 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507
Ashish Jain81eb2a82015-05-13 10:52:34 +05302508 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002509 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302510 adev->is_channel_status_set = true;
2511 }
2512
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002513 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002514 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002515 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002516 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002517 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2518 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302519 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2520 ALOGD("copl(%p):send next track params in gapless", out);
2521 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2522 out->send_next_track_params = false;
2523 out->is_compr_metadata_avail = false;
2524 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002525 }
2526
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002527 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302528 if (ret < 0)
2529 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302530 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002531 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302532 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002533 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302534 } else if (-ENETRESET == ret) {
2535 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2536 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2537 pthread_mutex_unlock(&out->lock);
2538 out_standby(&out->stream.common);
2539 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002540 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302541 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002542 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002543 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002544 out->playback_started = 1;
2545 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002546
2547 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2548 popcount(out->channel_mask),
2549 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002550 }
2551 pthread_mutex_unlock(&out->lock);
2552 return ret;
2553 } else {
2554 if (out->pcm) {
2555 if (out->muted)
2556 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002557
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302558 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002559
2560 if (adev->adm_request_focus)
2561 adev->adm_request_focus(adev->adm_data, out->handle);
2562
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002563 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2564 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2565 else
2566 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002567
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302568 if (ret < 0)
2569 ret = -errno;
2570 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002571 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002572
2573 if (adev->adm_abandon_focus)
2574 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002575 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576 }
2577
2578exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302579 /* ToDo: There may be a corner case when SSR happens back to back during
2580 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302581 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302582 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302583 }
2584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585 pthread_mutex_unlock(&out->lock);
2586
2587 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002588 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002589 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302590 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302591 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302592 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302593 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302594 out->standby = true;
2595 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302597 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302598 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 }
2600 return bytes;
2601}
2602
2603static int out_get_render_position(const struct audio_stream_out *stream,
2604 uint32_t *dsp_frames)
2605{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002606 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302607 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002608
2609 if (dsp_frames == NULL)
2610 return -EINVAL;
2611
2612 *dsp_frames = 0;
2613 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002614 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002615 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002616 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302617 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002618 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302619 if (ret < 0)
2620 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002621 ALOGVV("%s rendered frames %d sample_rate %d",
2622 __func__, *dsp_frames, out->sample_rate);
2623 }
2624 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302625 if (-ENETRESET == ret) {
2626 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2627 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2628 return -EINVAL;
2629 } else if(ret < 0) {
2630 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2631 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302632 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2633 /*
2634 * Handle corner case where compress session is closed during SSR
2635 * and timestamp is queried
2636 */
2637 ALOGE(" ERROR: sound card not active, return error");
2638 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302639 } else {
2640 return 0;
2641 }
Zhou Song32a556e2015-05-05 10:46:56 +08002642 } else if (audio_is_linear_pcm(out->format)) {
2643 *dsp_frames = out->written;
2644 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002645 } else
2646 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647}
2648
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002649static int out_add_audio_effect(const struct audio_stream *stream __unused,
2650 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651{
2652 return 0;
2653}
2654
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002655static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2656 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657{
2658 return 0;
2659}
2660
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002661static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2662 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663{
2664 return -EINVAL;
2665}
2666
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002667static int out_get_presentation_position(const struct audio_stream_out *stream,
2668 uint64_t *frames, struct timespec *timestamp)
2669{
2670 struct stream_out *out = (struct stream_out *)stream;
2671 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002672 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002673
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002674 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002675
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002676 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002677 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302678 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002679 &out->sample_rate);
2680 ALOGVV("%s rendered frames %ld sample_rate %d",
2681 __func__, dsp_frames, out->sample_rate);
2682 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302683 if (ret < 0)
2684 ret = -errno;
2685 if (-ENETRESET == ret) {
2686 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2687 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2688 ret = -EINVAL;
2689 } else
2690 ret = 0;
2691
Eric Laurent949a0892013-09-20 09:20:13 -07002692 /* this is the best we can do */
2693 clock_gettime(CLOCK_MONOTONIC, timestamp);
2694 }
2695 } else {
2696 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002697 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002698 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2699 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002700 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002701 // This adjustment accounts for buffering after app processor.
2702 // It is based on estimated DSP latency per use case, rather than exact.
2703 signed_frames -=
2704 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2705
Eric Laurent949a0892013-09-20 09:20:13 -07002706 // It would be unusual for this value to be negative, but check just in case ...
2707 if (signed_frames >= 0) {
2708 *frames = signed_frames;
2709 ret = 0;
2710 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002711 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302712 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2713 *frames = out->written;
2714 clock_gettime(CLOCK_MONOTONIC, timestamp);
2715 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002716 }
2717 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002718 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002719 return ret;
2720}
2721
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002722static int out_set_callback(struct audio_stream_out *stream,
2723 stream_callback_t callback, void *cookie)
2724{
2725 struct stream_out *out = (struct stream_out *)stream;
2726
2727 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002728 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002729 out->offload_callback = callback;
2730 out->offload_cookie = cookie;
2731 pthread_mutex_unlock(&out->lock);
2732 return 0;
2733}
2734
2735static int out_pause(struct audio_stream_out* stream)
2736{
2737 struct stream_out *out = (struct stream_out *)stream;
2738 int status = -ENOSYS;
2739 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002740 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002741 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002742 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002743 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302744 struct audio_device *adev = out->dev;
2745 int snd_scard_state = get_snd_card_state(adev);
2746
2747 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2748 status = compress_pause(out->compr);
2749
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002750 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002751
Mingming Yin21854652016-04-13 11:54:02 -07002752 if (audio_extn_passthru_is_active()) {
2753 ALOGV("offload use case, pause passthru");
2754 audio_extn_passthru_on_pause(out);
2755 }
2756
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302757 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002758 audio_extn_dts_notify_playback_state(out->usecase, 0,
2759 out->sample_rate, popcount(out->channel_mask),
2760 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002761 }
2762 pthread_mutex_unlock(&out->lock);
2763 }
2764 return status;
2765}
2766
2767static int out_resume(struct audio_stream_out* stream)
2768{
2769 struct stream_out *out = (struct stream_out *)stream;
2770 int status = -ENOSYS;
2771 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002772 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002773 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002774 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002775 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002776 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302777 struct audio_device *adev = out->dev;
2778 int snd_scard_state = get_snd_card_state(adev);
2779
Mingming Yin21854652016-04-13 11:54:02 -07002780 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
2781 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2782 pthread_mutex_lock(&out->dev->lock);
2783 ALOGV("offload resume, check and set hdmi backend again");
2784 check_and_set_hdmi_backend(out);
2785 pthread_mutex_unlock(&out->dev->lock);
2786 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302787 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07002788 }
2789 if (!status) {
2790 out->offload_state = OFFLOAD_STATE_PLAYING;
2791 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302792 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002793 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2794 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002795 }
2796 pthread_mutex_unlock(&out->lock);
2797 }
2798 return status;
2799}
2800
2801static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2802{
2803 struct stream_out *out = (struct stream_out *)stream;
2804 int status = -ENOSYS;
2805 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002806 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002807 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002808 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2809 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2810 else
2811 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2812 pthread_mutex_unlock(&out->lock);
2813 }
2814 return status;
2815}
2816
2817static int out_flush(struct audio_stream_out* stream)
2818{
2819 struct stream_out *out = (struct stream_out *)stream;
2820 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002821 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002822 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002823 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002824 stop_compressed_output_l(out);
2825 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002826 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002827 return 0;
2828 }
2829 return -ENOSYS;
2830}
2831
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832/** audio_stream_in implementation **/
2833static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2834{
2835 struct stream_in *in = (struct stream_in *)stream;
2836
2837 return in->config.rate;
2838}
2839
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002840static int in_set_sample_rate(struct audio_stream *stream __unused,
2841 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842{
2843 return -ENOSYS;
2844}
2845
2846static size_t in_get_buffer_size(const struct audio_stream *stream)
2847{
2848 struct stream_in *in = (struct stream_in *)stream;
2849
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002850 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2851 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002852 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2853 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002854
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002855 return in->config.period_size *
2856 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857}
2858
2859static uint32_t in_get_channels(const struct audio_stream *stream)
2860{
2861 struct stream_in *in = (struct stream_in *)stream;
2862
2863 return in->channel_mask;
2864}
2865
2866static audio_format_t in_get_format(const struct audio_stream *stream)
2867{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002868 struct stream_in *in = (struct stream_in *)stream;
2869
2870 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002871}
2872
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002873static int in_set_format(struct audio_stream *stream __unused,
2874 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875{
2876 return -ENOSYS;
2877}
2878
2879static int in_standby(struct audio_stream *stream)
2880{
2881 struct stream_in *in = (struct stream_in *)stream;
2882 struct audio_device *adev = in->dev;
2883 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302884 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2885 stream, in->usecase, use_case_table[in->usecase]);
2886
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002887 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2888 /* Ignore standby in case of voip call because the voip input
2889 * stream is closed in adev_close_input_stream()
2890 */
2891 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2892 return status;
2893 }
2894
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002895 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002896 if (!in->standby && in->is_st_session) {
2897 ALOGD("%s: sound trigger pcm stop lab", __func__);
2898 audio_extn_sound_trigger_stop_lab(in);
2899 in->standby = 1;
2900 }
2901
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002902 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002903 if (adev->adm_deregister_stream)
2904 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2905
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002906 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002907 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002908 if (in->pcm) {
2909 pcm_close(in->pcm);
2910 in->pcm = NULL;
2911 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002912 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002913 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002914 }
2915 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002916 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917 return status;
2918}
2919
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002920static int in_dump(const struct audio_stream *stream __unused,
2921 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922{
2923 return 0;
2924}
2925
2926static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2927{
2928 struct stream_in *in = (struct stream_in *)stream;
2929 struct audio_device *adev = in->dev;
2930 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002931 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002932 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002933
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302934 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002935 parms = str_parms_create_str(kvpairs);
2936
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302937 if (!parms)
2938 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002939 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002940 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002941
2942 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2943 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944 val = atoi(value);
2945 /* no audio source uses val == 0 */
2946 if ((in->source != val) && (val != 0)) {
2947 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002948 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2949 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2950 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08002951 (in->config.rate == 8000 || in->config.rate == 16000 ||
2952 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002953 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002954 err = voice_extn_compress_voip_open_input_stream(in);
2955 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002956 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002957 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002958 }
2959 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002960 }
2961 }
2962
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002963 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2964 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002965 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002966 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002967 in->device = val;
2968 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002969 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002970 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971 }
2972 }
2973
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002975 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976
2977 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302978error:
Eric Laurent994a6932013-07-17 11:51:42 -07002979 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980 return ret;
2981}
2982
2983static char* in_get_parameters(const struct audio_stream *stream,
2984 const char *keys)
2985{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002986 struct stream_in *in = (struct stream_in *)stream;
2987 struct str_parms *query = str_parms_create_str(keys);
2988 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002989 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002990
2991 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002992 if (reply) {
2993 str_parms_destroy(reply);
2994 }
2995 if (query) {
2996 str_parms_destroy(query);
2997 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002998 ALOGE("in_get_parameters: failed to create query or reply");
2999 return NULL;
3000 }
3001
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003002 ALOGV("%s: enter: keys - %s", __func__, keys);
3003
3004 voice_extn_in_get_parameters(in, query, reply);
3005
3006 str = str_parms_to_str(reply);
3007 str_parms_destroy(query);
3008 str_parms_destroy(reply);
3009
3010 ALOGV("%s: exit: returns - %s", __func__, str);
3011 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012}
3013
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003014static int in_set_gain(struct audio_stream_in *stream __unused,
3015 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016{
3017 return 0;
3018}
3019
3020static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3021 size_t bytes)
3022{
3023 struct stream_in *in = (struct stream_in *)stream;
3024 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303025 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303026 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003028 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303029
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003030 if (in->is_st_session) {
3031 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3032 /* Read from sound trigger HAL */
3033 audio_extn_sound_trigger_read(in, buffer, bytes);
3034 pthread_mutex_unlock(&in->lock);
3035 return bytes;
3036 }
3037
Ashish Jainbbce4322016-02-16 13:25:27 +05303038 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003039 ALOGD(" %s: sound card is not active/SSR state", __func__);
3040 ret= -EIO;;
3041 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303042 }
3043
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003044 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003045 pthread_mutex_lock(&adev->lock);
3046 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3047 ret = voice_extn_compress_voip_start_input_stream(in);
3048 else
3049 ret = start_input_stream(in);
3050 pthread_mutex_unlock(&adev->lock);
3051 if (ret != 0) {
3052 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053 }
3054 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003055 if (adev->adm_register_input_stream)
3056 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003059 if (adev->adm_request_focus)
3060 adev->adm_request_focus(adev->adm_data, in->capture_handle);
3061
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062 if (in->pcm) {
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003063 if (audio_extn_ssr_get_stream() == in)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003064 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07003065 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
3066 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003067 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
3068 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003069 else
3070 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303071 if (ret < 0)
3072 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 }
3074
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003075 if (adev->adm_abandon_focus)
3076 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
3077
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078 /*
3079 * Instead of writing zeroes here, we could trust the hardware
3080 * to always provide zeroes when muted.
3081 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303082 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3083 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084 memset(buffer, 0, bytes);
3085
3086exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303087 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303088 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003089 if (-ENETRESET == ret)
3090 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092 pthread_mutex_unlock(&in->lock);
3093
3094 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303095 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303096 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303097 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303098 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303099 in->standby = true;
3100 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303101 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003103 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303104 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303105 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106 }
3107 return bytes;
3108}
3109
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003110static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111{
3112 return 0;
3113}
3114
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003115static int add_remove_audio_effect(const struct audio_stream *stream,
3116 effect_handle_t effect,
3117 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003119 struct stream_in *in = (struct stream_in *)stream;
3120 int status = 0;
3121 effect_descriptor_t desc;
3122
3123 status = (*effect)->get_descriptor(effect, &desc);
3124 if (status != 0)
3125 return status;
3126
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003127 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003128 pthread_mutex_lock(&in->dev->lock);
3129 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3130 in->enable_aec != enable &&
3131 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3132 in->enable_aec = enable;
3133 if (!in->standby)
3134 select_devices(in->dev, in->usecase);
3135 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003136 if (in->enable_ns != enable &&
3137 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3138 in->enable_ns = enable;
3139 if (!in->standby)
3140 select_devices(in->dev, in->usecase);
3141 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003142 pthread_mutex_unlock(&in->dev->lock);
3143 pthread_mutex_unlock(&in->lock);
3144
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145 return 0;
3146}
3147
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003148static int in_add_audio_effect(const struct audio_stream *stream,
3149 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150{
Eric Laurent994a6932013-07-17 11:51:42 -07003151 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003152 return add_remove_audio_effect(stream, effect, true);
3153}
3154
3155static int in_remove_audio_effect(const struct audio_stream *stream,
3156 effect_handle_t effect)
3157{
Eric Laurent994a6932013-07-17 11:51:42 -07003158 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003159 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003160}
3161
3162static int adev_open_output_stream(struct audio_hw_device *dev,
3163 audio_io_handle_t handle,
3164 audio_devices_t devices,
3165 audio_output_flags_t flags,
3166 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003167 struct audio_stream_out **stream_out,
3168 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169{
3170 struct audio_device *adev = (struct audio_device *)dev;
3171 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303172 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003173 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303176
3177 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3178 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003179 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303180 return -EINVAL;
3181 }
3182
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003183 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3184
Mingming Yin3a941d42016-02-17 18:08:05 -08003185 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3186 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303187 devices, flags, &out->stream);
3188
3189
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003190 if (!out) {
3191 return -ENOMEM;
3192 }
3193
Haynes Mathew George204045b2015-02-25 20:32:03 -08003194 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003195 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003196 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3197
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198 if (devices == AUDIO_DEVICE_NONE)
3199 devices = AUDIO_DEVICE_OUT_SPEAKER;
3200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003201 out->flags = flags;
3202 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003203 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003204 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003205 out->sample_rate = config->sample_rate;
3206 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3207 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003208 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003209 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003210 out->non_blocking = 0;
3211 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212
Mingming Yin3a941d42016-02-17 18:08:05 -08003213 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3214 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3215 pthread_mutex_lock(&adev->lock);
3216 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3217 ret = read_hdmi_sink_caps(out);
3218 pthread_mutex_unlock(&adev->lock);
3219 if (ret != 0) {
3220 if (ret == -ENOSYS) {
3221 /* ignore and go with default */
3222 ret = 0;
3223 } else {
3224 ALOGE("error reading hdmi sink caps");
3225 goto error_open;
3226 }
3227 }
3228 }
3229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003231 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303232 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3233 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003234 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3235 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3236
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003237 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003238 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3239 /*
3240 * Do not handle stereo output in Multi-channel cases
3241 * Stereo case is handled in normal playback path
3242 */
3243 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3244 ret = AUDIO_CHANNEL_OUT_STEREO;
3245 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003246
3247 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3248 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003249 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003250 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003251 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003252
3253 if (config->sample_rate == 0)
3254 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3255 if (config->channel_mask == 0)
3256 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003257 if (config->format == 0)
3258 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003259
3260 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003261 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003262 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3264 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003265 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003266 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003267 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003268 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3269 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003270 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003271 ret = voice_extn_compress_voip_open_output_stream(out);
3272 if (ret != 0) {
3273 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3274 __func__, ret);
3275 goto error_open;
3276 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003277 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3278 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3279
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003280 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3281 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3282 ALOGE("%s: Unsupported Offload information", __func__);
3283 ret = -EINVAL;
3284 goto error_open;
3285 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003286
Mingming Yin3a941d42016-02-17 18:08:05 -08003287 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003288 if(config->offload_info.format == 0)
3289 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003290 if (config->offload_info.sample_rate == 0)
3291 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003292 }
3293
Mingming Yin90310102013-11-13 16:57:00 -08003294 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003295 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003296 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003297 ret = -EINVAL;
3298 goto error_open;
3299 }
3300
3301 out->compr_config.codec = (struct snd_codec *)
3302 calloc(1, sizeof(struct snd_codec));
3303
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003304 if (!out->compr_config.codec) {
3305 ret = -ENOMEM;
3306 goto error_open;
3307 }
3308
vivek mehta0ea887a2015-08-26 14:01:20 -07003309 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003310 out->usecase = get_offload_usecase(adev, true);
3311 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003312 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003313 out->stream.set_callback = out_set_callback;
3314 out->stream.pause = out_pause;
3315 out->stream.resume = out_resume;
3316 out->stream.drain = out_drain;
3317 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003318 out->usecase = get_offload_usecase(adev, false);
3319 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003320 }
vivek mehta446c3962015-09-14 10:57:35 -07003321
3322 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003323 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3324 config->format == 0 && config->sample_rate == 0 &&
3325 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003326 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003327 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3328 } else {
3329 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3330 ret = -EEXIST;
3331 goto error_open;
3332 }
vivek mehta446c3962015-09-14 10:57:35 -07003333 }
3334
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003335 if (config->offload_info.channel_mask)
3336 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003337 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003338 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003339 config->offload_info.channel_mask = config->channel_mask;
3340 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003341 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003342 out->sample_rate = config->offload_info.sample_rate;
3343
Mingming Yin3ee55c62014-08-04 14:23:35 -07003344 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003345
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003346 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003347 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003348 audio_extn_dolby_get_snd_codec_id(adev, out,
3349 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003350 else
3351 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003352 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003353
3354 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3355 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003356 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003357 platform_get_pcm_offload_buffer_size(&config->offload_info);
Mingming Yin21854652016-04-13 11:54:02 -07003358 } else if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003359 out->compr_config.fragment_size =
3360 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003361 } else {
3362 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003363 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003364 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003365 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3366 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003367 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003368 out->compr_config.codec->bit_rate =
3369 config->offload_info.bit_rate;
3370 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003371 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003372 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303373 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003374 /*TODO: Do we need to change it for passthrough */
3375 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003376
Manish Dewangana6fc5442015-08-24 20:30:31 +05303377 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3378 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3379 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3380 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003381 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3382 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003383 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003384 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003385 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3386 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003387
Mingming Yin3ee55c62014-08-04 14:23:35 -07003388 if (out->bit_width == 24) {
3389 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3390 }
3391
Amit Shekhar6f461b12014-08-01 14:52:58 -07003392 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303393 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003394
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003395 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3396 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003397
Mingming Yin497419f2015-07-01 16:57:32 -07003398 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003399 //this flag is set from framework only if its for PCM formats
3400 //no need to check for PCM format again
3401 out->non_blocking = 0;
3402 out->use_small_bufs = true;
3403 ALOGI("Keep write blocking for small buff: non_blockling %d",
3404 out->non_blocking);
3405 }
3406
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003407 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303408 out->send_next_track_params = false;
3409 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003410 out->offload_state = OFFLOAD_STATE_IDLE;
3411 out->playback_started = 0;
3412
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003413 audio_extn_dts_create_state_notifier_node(out->usecase);
3414
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003415 create_offload_callback_thread(out);
3416 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3417 __func__, config->offload_info.version,
3418 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003419 //Decide if we need to use gapless mode by default
Mingming Yin21854652016-04-13 11:54:02 -07003420 if (!audio_extn_dolby_is_passthrough_stream(out)) {
3421 ALOGV("%s: don't enable gapless for passthrough", __func__);
3422 check_and_set_gapless_mode(adev);
3423 }
3424
3425 if (audio_extn_dolby_is_passthrough_stream(out)) {
3426 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3427 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003428 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303429 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003430 if (ret != 0) {
3431 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3432 __func__, ret);
3433 goto error_open;
3434 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003435 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3436 if (config->sample_rate == 0)
3437 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3438 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3439 config->sample_rate != 8000) {
3440 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3441 ret = -EINVAL;
3442 goto error_open;
3443 }
3444 out->sample_rate = config->sample_rate;
3445 out->config.rate = config->sample_rate;
3446 if (config->format == AUDIO_FORMAT_DEFAULT)
3447 config->format = AUDIO_FORMAT_PCM_16_BIT;
3448 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3449 config->format = AUDIO_FORMAT_PCM_16_BIT;
3450 ret = -EINVAL;
3451 goto error_open;
3452 }
3453 out->format = config->format;
3454 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3455 out->config = pcm_config_afe_proxy_playback;
3456 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003457 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3458 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3459 out->config = pcm_config_low_latency;
3460 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003461 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003462 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3464 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003465 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003466 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3467 format = AUDIO_FORMAT_PCM_16_BIT;
3468 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3469 out->config = pcm_config_deep_buffer;
3470 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003471 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003472 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003473 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003474 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003475 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003476 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477 }
3478
Mingming Yin21854652016-04-13 11:54:02 -07003479 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d out->flags:%x, flags:%x",
3480 __func__, devices, flags, format, out->sample_rate, out->bit_width, out->flags, flags);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003481 /* TODO remove this hardcoding and check why width is zero*/
3482 if (out->bit_width == 0)
3483 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003484 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3485 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003486 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303487 out->bit_width, out->channel_mask,
3488 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003489 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3490 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3491 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003492 if(adev->primary_output == NULL)
3493 adev->primary_output = out;
3494 else {
3495 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003496 ret = -EEXIST;
3497 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003498 }
3499 }
3500
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501 /* Check if this usecase is already existing */
3502 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003503 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3504 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003507 ret = -EEXIST;
3508 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509 }
3510 pthread_mutex_unlock(&adev->lock);
3511
3512 out->stream.common.get_sample_rate = out_get_sample_rate;
3513 out->stream.common.set_sample_rate = out_set_sample_rate;
3514 out->stream.common.get_buffer_size = out_get_buffer_size;
3515 out->stream.common.get_channels = out_get_channels;
3516 out->stream.common.get_format = out_get_format;
3517 out->stream.common.set_format = out_set_format;
3518 out->stream.common.standby = out_standby;
3519 out->stream.common.dump = out_dump;
3520 out->stream.common.set_parameters = out_set_parameters;
3521 out->stream.common.get_parameters = out_get_parameters;
3522 out->stream.common.add_audio_effect = out_add_audio_effect;
3523 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3524 out->stream.get_latency = out_get_latency;
3525 out->stream.set_volume = out_set_volume;
3526 out->stream.write = out_write;
3527 out->stream.get_render_position = out_get_render_position;
3528 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003529 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003532 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003533 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534
3535 config->format = out->stream.common.get_format(&out->stream.common);
3536 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3537 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3538
3539 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303540 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003541 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003542
3543 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3544 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3545 popcount(out->channel_mask), out->playback_started);
3546
Eric Laurent994a6932013-07-17 11:51:42 -07003547 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003548 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003549
3550error_open:
3551 free(out);
3552 *stream_out = NULL;
3553 ALOGD("%s: exit: ret %d", __func__, ret);
3554 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555}
3556
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003557static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003558 struct audio_stream_out *stream)
3559{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003560 struct stream_out *out = (struct stream_out *)stream;
3561 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003562 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003563
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303564 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3565
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003566 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303567 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003568 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303569 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003570 if(ret != 0)
3571 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3572 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003573 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003574 out_standby(&stream->common);
3575
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003576 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003577 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003578 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003579 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003580 if (out->compr_config.codec != NULL)
3581 free(out->compr_config.codec);
3582 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003583
3584 if (adev->voice_tx_output == out)
3585 adev->voice_tx_output = NULL;
3586
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003587 pthread_cond_destroy(&out->cond);
3588 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003590 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591}
3592
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003593static void close_compress_sessions(struct audio_device *adev)
3594{
Mingming Yin7b762e72015-03-04 13:47:32 -08003595 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303596 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003597 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003598 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303599
3600 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003601 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303602 if (is_offload_usecase(usecase->id)) {
3603 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003604 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3605 out = usecase->stream.out;
3606 pthread_mutex_unlock(&adev->lock);
3607 out_standby(&out->stream.common);
3608 pthread_mutex_lock(&adev->lock);
3609 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303610 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003611 }
3612 pthread_mutex_unlock(&adev->lock);
3613}
3614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3616{
3617 struct audio_device *adev = (struct audio_device *)dev;
3618 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003620 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003621 int ret;
3622 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003624 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303627 if (!parms)
3628 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003629 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3630 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303631 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303632 if (strstr(snd_card_status, "OFFLINE")) {
3633 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303634 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003635 //close compress sessions on OFFLINE status
3636 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303637 } else if (strstr(snd_card_status, "ONLINE")) {
3638 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303639 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003640 //send dts hpx license if enabled
3641 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303642 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303643 }
3644
3645 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003646 status = voice_set_parameters(adev, parms);
3647 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003648 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003650 status = platform_set_parameters(adev->platform, parms);
3651 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003652 goto done;
3653
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003654 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3655 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003656 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3658 adev->bluetooth_nrec = true;
3659 else
3660 adev->bluetooth_nrec = false;
3661 }
3662
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003663 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3664 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003665 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3666 adev->screen_off = false;
3667 else
3668 adev->screen_off = true;
3669 }
3670
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003671 ret = str_parms_get_int(parms, "rotation", &val);
3672 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003673 bool reverse_speakers = false;
3674 switch(val) {
3675 // FIXME: note that the code below assumes that the speakers are in the correct placement
3676 // relative to the user when the device is rotated 90deg from its default rotation. This
3677 // assumption is device-specific, not platform-specific like this code.
3678 case 270:
3679 reverse_speakers = true;
3680 break;
3681 case 0:
3682 case 90:
3683 case 180:
3684 break;
3685 default:
3686 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003687 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003688 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003689 if (status == 0) {
3690 if (adev->speaker_lr_swap != reverse_speakers) {
3691 adev->speaker_lr_swap = reverse_speakers;
3692 // only update the selected device if there is active pcm playback
3693 struct audio_usecase *usecase;
3694 struct listnode *node;
3695 list_for_each(node, &adev->usecase_list) {
3696 usecase = node_to_item(node, struct audio_usecase, list);
3697 if (usecase->type == PCM_PLAYBACK) {
3698 select_devices(adev, usecase->id);
3699 break;
3700 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003701 }
3702 }
3703 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003704 }
3705
Mingming Yin514a8bc2014-07-29 15:22:21 -07003706 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3707 if (ret >= 0) {
3708 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3709 adev->bt_wb_speech_enabled = true;
3710 else
3711 adev->bt_wb_speech_enabled = false;
3712 }
3713
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003714 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3715 if (ret >= 0) {
3716 val = atoi(value);
3717 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3718 ALOGV("cache new edid");
3719 platform_cache_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003720 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3721 /*
3722 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
3723 * Per AudioPolicyManager, USB device is higher priority than WFD.
3724 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
3725 * If WFD use case occupies AFE proxy, it may result unintended behavior while
3726 * starting voice call on USB
3727 */
3728 ALOGV("detected USB connect .. disable proxy");
3729 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003730 }
3731 }
3732
3733 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3734 if (ret >= 0) {
3735 val = atoi(value);
3736 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3737 ALOGV("invalidate cached edid");
3738 platform_invalidate_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003739 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3740 ALOGV("detected USB disconnect .. enable proxy");
3741 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003742 }
3743 }
3744
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003745 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003746
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003747done:
3748 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003749 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303750error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003751 ALOGV("%s: exit with code(%d)", __func__, status);
3752 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003753}
3754
3755static char* adev_get_parameters(const struct audio_hw_device *dev,
3756 const char *keys)
3757{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003758 struct audio_device *adev = (struct audio_device *)dev;
3759 struct str_parms *reply = str_parms_create();
3760 struct str_parms *query = str_parms_create_str(keys);
3761 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303762 char value[256] = {0};
3763 int ret = 0;
3764
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003765 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003766 if (reply) {
3767 str_parms_destroy(reply);
3768 }
3769 if (query) {
3770 str_parms_destroy(query);
3771 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003772 ALOGE("adev_get_parameters: failed to create query or reply");
3773 return NULL;
3774 }
3775
Naresh Tannirud7205b62014-06-20 02:54:48 +05303776 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3777 sizeof(value));
3778 if (ret >=0) {
3779 int val = 1;
3780 pthread_mutex_lock(&adev->snd_card_status.lock);
3781 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3782 val = 0;
3783 pthread_mutex_unlock(&adev->snd_card_status.lock);
3784 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3785 goto exit;
3786 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003787
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003788 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003789 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003790 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003791 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303792 pthread_mutex_unlock(&adev->lock);
3793
Naresh Tannirud7205b62014-06-20 02:54:48 +05303794exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003795 str = str_parms_to_str(reply);
3796 str_parms_destroy(query);
3797 str_parms_destroy(reply);
3798
3799 ALOGV("%s: exit: returns - %s", __func__, str);
3800 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801}
3802
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003803static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804{
3805 return 0;
3806}
3807
3808static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3809{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003810 int ret;
3811 struct audio_device *adev = (struct audio_device *)dev;
3812 pthread_mutex_lock(&adev->lock);
3813 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003814 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003815 pthread_mutex_unlock(&adev->lock);
3816 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817}
3818
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003819static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3820 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821{
3822 return -ENOSYS;
3823}
3824
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003825static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3826 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003827{
3828 return -ENOSYS;
3829}
3830
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003831static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3832 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003833{
3834 return -ENOSYS;
3835}
3836
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003837static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3838 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839{
3840 return -ENOSYS;
3841}
3842
3843static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3844{
3845 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003846
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003847 pthread_mutex_lock(&adev->lock);
3848 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003849 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003850 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003851 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003852 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003853 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003854 adev->current_call_output = NULL;
3855 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003856 }
3857 pthread_mutex_unlock(&adev->lock);
3858 return 0;
3859}
3860
3861static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3862{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003863 int ret;
3864
3865 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003866 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003867 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3868 pthread_mutex_unlock(&adev->lock);
3869
3870 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871}
3872
3873static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3874{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003875 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003876 return 0;
3877}
3878
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003879static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003880 const struct audio_config *config)
3881{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003882 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003883
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003884 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3885 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886}
3887
3888static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003889 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003890 audio_devices_t devices,
3891 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003892 struct audio_stream_in **stream_in,
3893 audio_input_flags_t flags __unused,
3894 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003895 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003896{
3897 struct audio_device *adev = (struct audio_device *)dev;
3898 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003899 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003900 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003901 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303902
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903 *stream_in = NULL;
3904 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3905 return -EINVAL;
3906
3907 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003908
3909 if (!in) {
3910 ALOGE("failed to allocate input stream");
3911 return -ENOMEM;
3912 }
3913
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303914 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003915 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3916 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003918 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003919 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003921 in->stream.common.get_sample_rate = in_get_sample_rate;
3922 in->stream.common.set_sample_rate = in_set_sample_rate;
3923 in->stream.common.get_buffer_size = in_get_buffer_size;
3924 in->stream.common.get_channels = in_get_channels;
3925 in->stream.common.get_format = in_get_format;
3926 in->stream.common.set_format = in_set_format;
3927 in->stream.common.standby = in_standby;
3928 in->stream.common.dump = in_dump;
3929 in->stream.common.set_parameters = in_set_parameters;
3930 in->stream.common.get_parameters = in_get_parameters;
3931 in->stream.common.add_audio_effect = in_add_audio_effect;
3932 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3933 in->stream.set_gain = in_set_gain;
3934 in->stream.read = in_read;
3935 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3936
3937 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003938 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003939 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003940 in->standby = 1;
3941 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003942 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003943 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003944
3945 /* Update config params with the requested sample rate and channels */
3946 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003947 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3948 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3949 is_low_latency = true;
3950#if LOW_LATENCY_CAPTURE_USE_CASE
3951 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3952#endif
3953 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003955 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003956 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003957
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003958 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303959 if (adev->mode != AUDIO_MODE_IN_CALL) {
3960 ret = -EINVAL;
3961 goto err_open;
3962 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003963 if (config->sample_rate == 0)
3964 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3965 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3966 config->sample_rate != 8000) {
3967 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3968 ret = -EINVAL;
3969 goto err_open;
3970 }
3971 if (config->format == AUDIO_FORMAT_DEFAULT)
3972 config->format = AUDIO_FORMAT_PCM_16_BIT;
3973 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3974 config->format = AUDIO_FORMAT_PCM_16_BIT;
3975 ret = -EINVAL;
3976 goto err_open;
3977 }
3978
3979 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3980 in->config = pcm_config_afe_proxy_record;
3981 in->config.channels = channel_count;
3982 in->config.rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05303983 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
3984 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07003985 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003986 audio_extn_compr_cap_format_supported(config->format) &&
3987 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003988 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003989 } else {
3990 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003991 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003992 buffer_size = get_input_buffer_size(config->sample_rate,
3993 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003994 channel_count,
3995 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003996 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003997 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3998 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3999 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004000 (in->config.rate == 8000 || in->config.rate == 16000 ||
4001 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004002 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4003 voice_extn_compress_voip_open_input_stream(in);
4004 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004005 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004006
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004007 /* This stream could be for sound trigger lab,
4008 get sound trigger pcm if present */
4009 audio_extn_sound_trigger_check_and_get_session(in);
4010
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004011 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004012 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004013 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004014
4015err_open:
4016 free(in);
4017 *stream_in = NULL;
4018 return ret;
4019}
4020
4021static void adev_close_input_stream(struct audio_hw_device *dev,
4022 struct audio_stream_in *stream)
4023{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004024 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004025 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004026 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304027
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304028 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004029
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304030 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004031 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304032
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004033 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304034 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004035 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304036 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004037 if (ret != 0)
4038 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4039 __func__, ret);
4040 } else
4041 in_standby(&stream->common);
4042
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004043 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004044 audio_extn_ssr_deinit();
4045 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046
Mingming Yine62d7842013-10-25 16:26:03 -07004047 if(audio_extn_compr_cap_enabled() &&
4048 audio_extn_compr_cap_format_supported(in->config.format))
4049 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004050
Mingming Yinfd7607b2016-01-22 12:48:44 -08004051 if (in->is_st_session) {
4052 ALOGV("%s: sound trigger pcm stop lab", __func__);
4053 audio_extn_sound_trigger_stop_lab(in);
4054 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004055 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004056 return;
4057}
4058
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004059static int adev_dump(const audio_hw_device_t *device __unused,
4060 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061{
4062 return 0;
4063}
4064
4065static int adev_close(hw_device_t *device)
4066{
4067 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004068
4069 if (!adev)
4070 return 0;
4071
4072 pthread_mutex_lock(&adev_init_lock);
4073
4074 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004075 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004076 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004077 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004078 audio_route_free(adev->audio_route);
4079 free(adev->snd_dev_ref_cnt);
4080 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004081 if (adev->adm_deinit)
4082 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004083 free(device);
4084 adev = NULL;
4085 }
4086 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004088 return 0;
4089}
4090
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004091/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4092 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4093 * just that it _might_ work.
4094 */
4095static int period_size_is_plausible_for_low_latency(int period_size)
4096{
4097 switch (period_size) {
4098 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004099 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004100 case 240:
4101 case 320:
4102 case 480:
4103 return 1;
4104 default:
4105 return 0;
4106 }
4107}
4108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004109static int adev_open(const hw_module_t *module, const char *name,
4110 hw_device_t **device)
4111{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004112 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004113 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4114
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004115 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004116 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004117 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004118 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004119 ALOGD("%s: returning existing instance of adev", __func__);
4120 ALOGD("%s: exit", __func__);
4121 pthread_mutex_unlock(&adev_init_lock);
4122 return 0;
4123 }
4124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004125 adev = calloc(1, sizeof(struct audio_device));
4126
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004127 if (!adev) {
4128 pthread_mutex_unlock(&adev_init_lock);
4129 return -ENOMEM;
4130 }
4131
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004132 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004134 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4135 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4136 adev->device.common.module = (struct hw_module_t *)module;
4137 adev->device.common.close = adev_close;
4138
4139 adev->device.init_check = adev_init_check;
4140 adev->device.set_voice_volume = adev_set_voice_volume;
4141 adev->device.set_master_volume = adev_set_master_volume;
4142 adev->device.get_master_volume = adev_get_master_volume;
4143 adev->device.set_master_mute = adev_set_master_mute;
4144 adev->device.get_master_mute = adev_get_master_mute;
4145 adev->device.set_mode = adev_set_mode;
4146 adev->device.set_mic_mute = adev_set_mic_mute;
4147 adev->device.get_mic_mute = adev_get_mic_mute;
4148 adev->device.set_parameters = adev_set_parameters;
4149 adev->device.get_parameters = adev_get_parameters;
4150 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4151 adev->device.open_output_stream = adev_open_output_stream;
4152 adev->device.close_output_stream = adev_close_output_stream;
4153 adev->device.open_input_stream = adev_open_input_stream;
4154 adev->device.close_input_stream = adev_close_input_stream;
4155 adev->device.dump = adev_dump;
4156
4157 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004158 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004159 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004160 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004163 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004164 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004165 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004166 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004167 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004168 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004169 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004170 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304171 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304172 adev->perf_lock_opts[0] = 0x101;
4173 adev->perf_lock_opts[1] = 0x20E;
4174 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304175
4176 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4177 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004178 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004179 adev->platform = platform_init(adev);
4180 if (!adev->platform) {
4181 free(adev->snd_dev_ref_cnt);
4182 free(adev);
4183 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4184 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004185 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004186 return -EINVAL;
4187 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004188
Naresh Tanniru4c630392014-05-12 01:05:52 +05304189 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4190
Eric Laurentc4aef752013-09-12 17:45:53 -07004191 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4192 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4193 if (adev->visualizer_lib == NULL) {
4194 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4195 } else {
4196 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4197 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004198 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004199 "visualizer_hal_start_output");
4200 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004201 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004202 "visualizer_hal_stop_output");
4203 }
4204 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004205 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004206 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004207
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004208 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4209 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4210 if (adev->offload_effects_lib == NULL) {
4211 ALOGE("%s: DLOPEN failed for %s", __func__,
4212 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4213 } else {
4214 ALOGV("%s: DLOPEN successful for %s", __func__,
4215 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4216 adev->offload_effects_start_output =
4217 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4218 "offload_effects_bundle_hal_start_output");
4219 adev->offload_effects_stop_output =
4220 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4221 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004222 adev->offload_effects_set_hpx_state =
4223 (int (*)(bool))dlsym(adev->offload_effects_lib,
4224 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304225 adev->offload_effects_get_parameters =
4226 (void (*)(struct str_parms *, struct str_parms *))
4227 dlsym(adev->offload_effects_lib,
4228 "offload_effects_bundle_get_parameters");
4229 adev->offload_effects_set_parameters =
4230 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4231 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004232 }
4233 }
4234
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004235 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4236 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4237 if (adev->adm_lib == NULL) {
4238 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4239 } else {
4240 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4241 adev->adm_init = (adm_init_t)
4242 dlsym(adev->adm_lib, "adm_init");
4243 adev->adm_deinit = (adm_deinit_t)
4244 dlsym(adev->adm_lib, "adm_deinit");
4245 adev->adm_register_input_stream = (adm_register_input_stream_t)
4246 dlsym(adev->adm_lib, "adm_register_input_stream");
4247 adev->adm_register_output_stream = (adm_register_output_stream_t)
4248 dlsym(adev->adm_lib, "adm_register_output_stream");
4249 adev->adm_deregister_stream = (adm_deregister_stream_t)
4250 dlsym(adev->adm_lib, "adm_deregister_stream");
4251 adev->adm_request_focus = (adm_request_focus_t)
4252 dlsym(adev->adm_lib, "adm_request_focus");
4253 adev->adm_abandon_focus = (adm_abandon_focus_t)
4254 dlsym(adev->adm_lib, "adm_abandon_focus");
4255 }
4256 }
4257
Mingming Yin514a8bc2014-07-29 15:22:21 -07004258 adev->bt_wb_speech_enabled = false;
4259
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004260 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004261 *device = &adev->device.common;
4262
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004263 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4264 &adev->streams_output_cfg_list);
4265
Kiran Kandi910e1862013-10-29 13:29:42 -07004266 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004267
4268 char value[PROPERTY_VALUE_MAX];
4269 int trial;
4270 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4271 trial = atoi(value);
4272 if (period_size_is_plausible_for_low_latency(trial)) {
4273 pcm_config_low_latency.period_size = trial;
4274 pcm_config_low_latency.start_threshold = trial / 4;
4275 pcm_config_low_latency.avail_min = trial / 4;
4276 configured_low_latency_capture_period_size = trial;
4277 }
4278 }
4279 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4280 trial = atoi(value);
4281 if (period_size_is_plausible_for_low_latency(trial)) {
4282 configured_low_latency_capture_period_size = trial;
4283 }
4284 }
4285
vivek mehta446c3962015-09-14 10:57:35 -07004286 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004287 pthread_mutex_unlock(&adev_init_lock);
4288
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004289 if (adev->adm_init)
4290 adev->adm_data = adev->adm_init();
4291
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304292 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004293 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004294 return 0;
4295}
4296
4297static struct hw_module_methods_t hal_module_methods = {
4298 .open = adev_open,
4299};
4300
4301struct audio_module HAL_MODULE_INFO_SYM = {
4302 .common = {
4303 .tag = HARDWARE_MODULE_TAG,
4304 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4305 .hal_api_version = HARDWARE_HAL_API_VERSION,
4306 .id = AUDIO_HARDWARE_MODULE_ID,
4307 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004308 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004309 .methods = &hal_module_methods,
4310 },
4311};