blob: 8486e1861328ad03386f5b46364b836ca86e1da4 [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{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530504 int i, num_devices = 0;
505 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700506 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
507
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800508 if (snd_device < SND_DEVICE_MIN ||
509 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800510 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800511 return -EINVAL;
512 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700513
514 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700515
516 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
517 ALOGE("%s: Invalid sound device returned", __func__);
518 return -EINVAL;
519 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700520 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700521 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700522 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700523 return 0;
524 }
525
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530526
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700527 if (audio_extn_spkr_prot_is_enabled())
528 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700529 /* start usb playback thread */
530 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
531 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
532 audio_extn_usb_start_playback(adev);
533
534 /* start usb capture thread */
535 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
536 audio_extn_usb_start_capture(adev);
537
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800538 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
539 audio_extn_spkr_prot_is_enabled()) {
540 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700541 adev->snd_dev_ref_cnt[snd_device]--;
542 return -EINVAL;
543 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200544 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800545 if (audio_extn_spkr_prot_start_processing(snd_device)) {
546 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200547 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800548 return -EINVAL;
549 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530550 } else if (platform_can_split_snd_device(adev->platform, snd_device,
551 &num_devices, new_snd_devices)) {
552 for (i = 0; i < num_devices; i++) {
553 enable_snd_device(adev, new_snd_devices[i]);
554 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800555 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700556 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700557 /* due to the possibility of calibration overwrite between listen
558 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700559 audio_extn_sound_trigger_update_device_status(snd_device,
560 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530561 audio_extn_listen_update_device_status(snd_device,
562 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700563 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700564 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700565 audio_extn_sound_trigger_update_device_status(snd_device,
566 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530567 audio_extn_listen_update_device_status(snd_device,
568 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700569 return -EINVAL;
570 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300571 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700572 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530573
574 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
575 !adev->native_playback_enabled &&
576 audio_is_true_native_stream_active(adev)) {
577 ALOGD("%s: %d: napb: enabling native mode in hardware",
578 __func__, __LINE__);
579 audio_route_apply_and_update_path(adev->audio_route,
580 "true-native-mode");
581 adev->native_playback_enabled = true;
582 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800583 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800584 return 0;
585}
586
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700587int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700588 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800589{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530590 int i, num_devices = 0;
591 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700592 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
593
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800594 if (snd_device < SND_DEVICE_MIN ||
595 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800596 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800597 return -EINVAL;
598 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700599 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
600 ALOGE("%s: device ref cnt is already 0", __func__);
601 return -EINVAL;
602 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700603
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700604 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700605
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700606 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
607 ALOGE("%s: Invalid sound device returned", __func__);
608 return -EINVAL;
609 }
610
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700611 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700612 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800613 /* exit usb play back thread */
614 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
615 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
616 audio_extn_usb_stop_playback();
617
618 /* exit usb capture thread */
619 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700620 audio_extn_usb_stop_capture();
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800621
622 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
623 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700624 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530625 } else if (platform_can_split_snd_device(adev->platform, snd_device,
626 &num_devices, new_snd_devices)) {
627 for (i = 0; i < num_devices; i++) {
628 disable_snd_device(adev, new_snd_devices[i]);
629 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300630 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700631 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300632 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700633
Ashish Jain81eb2a82015-05-13 10:52:34 +0530634 if (snd_device == SND_DEVICE_OUT_HDMI)
635 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530636 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
637 adev->native_playback_enabled) {
638 ALOGD("%s: %d: napb: disabling native mode in hardware",
639 __func__, __LINE__);
640 audio_route_reset_and_update_path(adev->audio_route,
641 "true-native-mode");
642 adev->native_playback_enabled = false;
643 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530644
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200645 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700646 audio_extn_sound_trigger_update_device_status(snd_device,
647 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530648 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800649 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700650 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800652 return 0;
653}
654
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700655static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530656 struct audio_usecase *uc_info,
657 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700658{
659 struct listnode *node;
660 struct audio_usecase *usecase;
661 bool switch_device[AUDIO_USECASE_MAX];
662 int i, num_uc_to_switch = 0;
663
664 /*
665 * This function is to make sure that all the usecases that are active on
666 * the hardware codec backend are always routed to any one device that is
667 * handled by the hardware codec.
668 * For example, if low-latency and deep-buffer usecases are currently active
669 * on speaker and out_set_parameters(headset) is received on low-latency
670 * output, then we have to make sure deep-buffer is also switched to headset,
671 * because of the limitation that both the devices cannot be enabled
672 * at the same time as they share the same backend.
673 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700674 /*
675 * This call is to check if we need to force routing for a particular stream
676 * If there is a backend configuration change for the device when a
677 * new stream starts, then ADM needs to be closed and re-opened with the new
678 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800679 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700680 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800681 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
682 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530683
684 ALOGD("%s:becf: force routing %d", __func__, force_routing);
685
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800687 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800688 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700689 for (i = 0; i < AUDIO_USECASE_MAX; i++)
690 switch_device[i] = false;
691
692 list_for_each(node, &adev->usecase_list) {
693 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800694
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530695 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
696 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530697 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530698 platform_get_snd_device_name(usecase->out_snd_device),
699 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800700 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530701 usecase != uc_info &&
702 (usecase->out_snd_device != snd_device || force_routing) &&
703 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
704 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
705 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
706 __func__, use_case_table[usecase->id],
707 platform_get_snd_device_name(usecase->out_snd_device));
708 disable_audio_route(adev, usecase);
709 switch_device[usecase->id] = true;
710 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700711 }
712 }
713
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530714 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
715 num_uc_to_switch);
716
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700717 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700718 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700719
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530720 /* Make sure the previous devices to be disabled first and then enable the
721 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -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 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700726 }
727 }
728
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700729 list_for_each(node, &adev->usecase_list) {
730 usecase = node_to_item(node, struct audio_usecase, list);
731 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700732 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700733 }
734 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700735
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700736 /* Re-route all the usecases on the shared backend other than the
737 specified usecase to new snd devices */
738 list_for_each(node, &adev->usecase_list) {
739 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530740 /* Update the out_snd_device only before enabling the audio route */
741 if (switch_device[usecase->id]) {
742 usecase->out_snd_device = snd_device;
743 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530744 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530745 use_case_table[usecase->id],
746 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530747 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530748 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700749 }
750 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700751 }
752}
753
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530754static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700755 struct audio_usecase *uc_info,
756 snd_device_t snd_device)
757{
758 struct listnode *node;
759 struct audio_usecase *usecase;
760 bool switch_device[AUDIO_USECASE_MAX];
761 int i, num_uc_to_switch = 0;
762
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530763 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
764 snd_device);
765 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700766 /*
767 * This function is to make sure that all the active capture usecases
768 * are always routed to the same input sound device.
769 * For example, if audio-record and voice-call usecases are currently
770 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
771 * is received for voice call then we have to make sure that audio-record
772 * usecase is also switched to earpiece i.e. voice-dmic-ef,
773 * because of the limitation that two devices cannot be enabled
774 * at the same time if they share the same backend.
775 */
776 for (i = 0; i < AUDIO_USECASE_MAX; i++)
777 switch_device[i] = false;
778
779 list_for_each(node, &adev->usecase_list) {
780 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800781 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700782 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530783 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700784 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530785 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
786 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700787 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700788 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
789 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700790 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700791 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700792 switch_device[usecase->id] = true;
793 num_uc_to_switch++;
794 }
795 }
796
797 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700798 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700799
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530800 /* Make sure the previous devices to be disabled first and then enable the
801 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700802 list_for_each(node, &adev->usecase_list) {
803 usecase = node_to_item(node, struct audio_usecase, list);
804 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700805 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800806 }
807 }
808
809 list_for_each(node, &adev->usecase_list) {
810 usecase = node_to_item(node, struct audio_usecase, list);
811 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700812 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700813 }
814 }
815
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700816 /* Re-route all the usecases on the shared backend other than the
817 specified usecase to new snd devices */
818 list_for_each(node, &adev->usecase_list) {
819 usecase = node_to_item(node, struct audio_usecase, list);
820 /* Update the in_snd_device only before enabling the audio route */
821 if (switch_device[usecase->id] ) {
822 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800823 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530824 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700825 }
826 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700827 }
828}
829
Mingming Yin3a941d42016-02-17 18:08:05 -0800830static void reset_hdmi_sink_caps(struct stream_out *out) {
831 int i = 0;
832
833 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
834 out->supported_channel_masks[i] = 0;
835 }
836 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
837 out->supported_formats[i] = 0;
838 }
839 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
840 out->supported_sample_rates[i] = 0;
841 }
842}
843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800844/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -0800845static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800846{
Mingming Yin3a941d42016-02-17 18:08:05 -0800847 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700848 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800849
Mingming Yin3a941d42016-02-17 18:08:05 -0800850 reset_hdmi_sink_caps(out);
851
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800852 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800853 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -0800854 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700855 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -0800856 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
857 case 6:
858 ALOGV("%s: HDMI supports 5.1 channels", __func__);
859 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
860 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
861 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
862 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
863 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
864 case 2:
865 ALOGV("%s: HDMI supports 2 channels", __func__);
866 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_STEREO;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800867 break;
868 default:
Mingming Yin3a941d42016-02-17 18:08:05 -0800869 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700870 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800871 break;
872 }
Mingming Yin3a941d42016-02-17 18:08:05 -0800873
874 // check channel format caps
875 i = 0;
876 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
877 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
878 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
879 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
880 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
881 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
882 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
883 }
884
885 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
886 ALOGV(":%s HDMI supports DTS format", __func__);
887 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
888 }
889
890 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
891 ALOGV(":%s HDMI supports DTS HD format", __func__);
892 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
893 }
894
895
896 // check sample rate caps
897 i = 0;
898 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
899 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
900 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
901 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
902 }
903 }
904
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700905 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800906}
907
Alexy Josephb1379942016-01-29 15:49:38 -0800908audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800909 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700910{
911 struct audio_usecase *usecase;
912 struct listnode *node;
913
914 list_for_each(node, &adev->usecase_list) {
915 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800916 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700917 ALOGV("%s: usecase id %d", __func__, usecase->id);
918 return usecase->id;
919 }
920 }
921 return USECASE_INVALID;
922}
923
Alexy Josephb1379942016-01-29 15:49:38 -0800924struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700925 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700926{
927 struct audio_usecase *usecase;
928 struct listnode *node;
929
930 list_for_each(node, &adev->usecase_list) {
931 usecase = node_to_item(node, struct audio_usecase, list);
932 if (usecase->id == uc_id)
933 return usecase;
934 }
935 return NULL;
936}
937
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530938/*
939 * is a true native playback active
940 */
941bool audio_is_true_native_stream_active(struct audio_device *adev)
942{
943 bool active = false;
944 int i = 0;
945 struct listnode *node;
946
947 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
948 ALOGV("%s:napb: not in true mode or non hdphones device",
949 __func__);
950 active = false;
951 goto exit;
952 }
953
954 list_for_each(node, &adev->usecase_list) {
955 struct audio_usecase *uc;
956 uc = node_to_item(node, struct audio_usecase, list);
957 struct stream_out *curr_out =
958 (struct stream_out*) uc->stream.out;
959
960 if (curr_out && PCM_PLAYBACK == uc->type) {
961 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
962 "(%d) device %s", __func__, i++, use_case_table[uc->id],
963 uc->id, curr_out->sample_rate,
964 curr_out->bit_width,
965 platform_get_snd_device_name(uc->out_snd_device));
966
967 if (is_offload_usecase(uc->id) &&
968 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
969 active = true;
970 ALOGD("%s:napb:native stream detected", __func__);
971 }
972 }
973 }
974exit:
975 return active;
976}
977
978
979static bool force_device_switch(struct audio_usecase *usecase)
980{
981 bool ret = false;
982 bool is_it_true_mode = false;
983
984 if (is_offload_usecase(usecase->id) &&
985 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +0800986 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
987 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
988 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530989 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
990 if ((is_it_true_mode && !adev->native_playback_enabled) ||
991 (!is_it_true_mode && adev->native_playback_enabled)){
992 ret = true;
993 ALOGD("napb: time to toggle native mode");
994 }
995 }
996
997 return ret;
998}
999
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001000int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001001{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001002 snd_device_t out_snd_device = SND_DEVICE_NONE;
1003 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001004 struct audio_usecase *usecase = NULL;
1005 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001006 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001007 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001008 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001009 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001010
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301011 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1012
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001013 usecase = get_usecase_from_list(adev, uc_id);
1014 if (usecase == NULL) {
1015 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1016 return -EINVAL;
1017 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001019 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001020 (usecase->type == VOIP_CALL) ||
1021 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001022 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001023 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001024 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001025 usecase->devices = usecase->stream.out->devices;
1026 } else {
1027 /*
1028 * If the voice call is active, use the sound devices of voice call usecase
1029 * so that it would not result any device switch. All the usecases will
1030 * be switched to new device when select_devices() is called for voice call
1031 * usecase. This is to avoid switching devices for voice call when
1032 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001033 * choose voice call device only if the use case device is
1034 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001035 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001036 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001037 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001038 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001039 if (((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1040 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND))) ||
1041 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001042 in_snd_device = vc_usecase->in_snd_device;
1043 out_snd_device = vc_usecase->out_snd_device;
1044 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001045 } else if (voice_extn_compress_voip_is_active(adev)) {
1046 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001047 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +05301048 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001049 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001050 in_snd_device = voip_usecase->in_snd_device;
1051 out_snd_device = voip_usecase->out_snd_device;
1052 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001053 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001054 hfp_ucid = audio_extn_hfp_get_usecase();
1055 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001056 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001057 in_snd_device = hfp_usecase->in_snd_device;
1058 out_snd_device = hfp_usecase->out_snd_device;
1059 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001060 }
1061 if (usecase->type == PCM_PLAYBACK) {
1062 usecase->devices = usecase->stream.out->devices;
1063 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001064 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001065 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001066 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001067 if (usecase->stream.out == adev->primary_output &&
1068 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001069 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001070 select_devices(adev, adev->active_input->usecase);
1071 }
1072 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001073 } else if (usecase->type == PCM_CAPTURE) {
1074 usecase->devices = usecase->stream.in->device;
1075 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001076 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001077 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001078 if (adev->active_input &&
1079 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301080 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1081 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1082 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001083 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001084 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001085 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1086 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001087 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001088 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001089 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001090 }
1091 }
1092
1093 if (out_snd_device == usecase->out_snd_device &&
1094 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301095
1096 if (!force_device_switch(usecase))
1097 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001098 }
1099
sangwoobc677242013-08-08 16:53:43 +09001100 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001101 out_snd_device, platform_get_snd_device_name(out_snd_device),
1102 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001103
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001104 /*
1105 * Limitation: While in call, to do a device switch we need to disable
1106 * and enable both RX and TX devices though one of them is same as current
1107 * device.
1108 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001109 if ((usecase->type == VOICE_CALL) &&
1110 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1111 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001112 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001113 }
1114
1115 if (((usecase->type == VOICE_CALL) ||
1116 (usecase->type == VOIP_CALL)) &&
1117 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1118 /* Disable sidetone only if voice/voip call already exists */
1119 if (voice_is_call_state_active(adev) ||
1120 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001121 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001122 }
1123
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001124 /* Disable current sound devices */
1125 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001126 disable_audio_route(adev, usecase);
1127 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001128 }
1129
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001130 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001131 disable_audio_route(adev, usecase);
1132 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001133 }
1134
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001135 /* Applicable only on the targets that has external modem.
1136 * New device information should be sent to modem before enabling
1137 * the devices to reduce in-call device switch time.
1138 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001139 if ((usecase->type == VOICE_CALL) &&
1140 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1141 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001142 status = platform_switch_voice_call_enable_device_config(adev->platform,
1143 out_snd_device,
1144 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001145 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001146
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001147 /* Enable new sound devices */
1148 if (out_snd_device != SND_DEVICE_NONE) {
1149 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
1150 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001151 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001152 }
1153
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001154 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301155 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001156 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001157 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001158
Avinash Vaish71a8b972014-07-24 15:36:33 +05301159 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001160 status = platform_switch_voice_call_device_post(adev->platform,
1161 out_snd_device,
1162 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301163 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001164 /* Enable sidetone only if voice/voip call already exists */
1165 if (voice_is_call_state_active(adev) ||
1166 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001167 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301168 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001169
sangwoo170731f2013-06-08 15:36:36 +09001170 usecase->in_snd_device = in_snd_device;
1171 usecase->out_snd_device = out_snd_device;
1172
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301173 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001174 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301175 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001176 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301177 usecase->stream.out->flags,
1178 usecase->stream.out->format,
1179 usecase->stream.out->sample_rate,
1180 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301181 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301182 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001183 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301184 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001185
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001186 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001187
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001188 /* Applicable only on the targets that has external modem.
1189 * Enable device command should be sent to modem only after
1190 * enabling voice call mixer controls
1191 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001192 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001193 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1194 out_snd_device,
1195 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301196 ALOGD("%s: done",__func__);
1197
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001198 return status;
1199}
1200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001201static int stop_input_stream(struct stream_in *in)
1202{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301203 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001204 struct audio_usecase *uc_info;
1205 struct audio_device *adev = in->dev;
1206
Eric Laurentc8400632013-02-14 19:04:54 -08001207 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001208
Eric Laurent994a6932013-07-17 11:51:42 -07001209 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001210 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001211 uc_info = get_usecase_from_list(adev, in->usecase);
1212 if (uc_info == NULL) {
1213 ALOGE("%s: Could not find the usecase (%d) in the list",
1214 __func__, in->usecase);
1215 return -EINVAL;
1216 }
1217
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001218 /* Close in-call recording streams */
1219 voice_check_and_stop_incall_rec_usecase(adev, in);
1220
Eric Laurent150dbfe2013-02-27 14:31:02 -08001221 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001222 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001223
1224 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001225 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001226
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001227 list_remove(&uc_info->list);
1228 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001229
Eric Laurent994a6932013-07-17 11:51:42 -07001230 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001231 return ret;
1232}
1233
1234int start_input_stream(struct stream_in *in)
1235{
1236 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001237 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001238 struct audio_usecase *uc_info;
1239 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301240 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001241
Mingming Yin2664a5b2015-09-03 10:53:11 -07001242 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1243 if (get_usecase_from_list(adev, usecase) == NULL)
1244 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301245 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1246 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001247
Naresh Tanniru80659832014-06-04 18:17:56 +05301248
1249 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301250 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301251 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301252 goto error_config;
1253 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301254
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001255 /* Check if source matches incall recording usecase criteria */
1256 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1257 if (ret)
1258 goto error_config;
1259 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001260 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1261
1262 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1263 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1264 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1265 goto error_config;
1266 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001267
Eric Laurentb23d5282013-05-14 15:27:20 -07001268 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001269 if (in->pcm_device_id < 0) {
1270 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1271 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001272 ret = -EINVAL;
1273 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001274 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001275
1276 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001277 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001278
1279 if (!uc_info) {
1280 ret = -ENOMEM;
1281 goto error_config;
1282 }
1283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001284 uc_info->id = in->usecase;
1285 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001286 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001287 uc_info->devices = in->device;
1288 uc_info->in_snd_device = SND_DEVICE_NONE;
1289 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001290
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001291 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301292 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1293 adev->perf_lock_opts,
1294 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001295 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001296
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301297 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1298 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001299
1300 unsigned int flags = PCM_IN;
1301 unsigned int pcm_open_retry_count = 0;
1302
1303 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1304 flags |= PCM_MMAP | PCM_NOIRQ;
1305 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1306 }
1307
1308 while (1) {
1309 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1310 flags, &in->config);
1311 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1312 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1313 if (in->pcm != NULL) {
1314 pcm_close(in->pcm);
1315 in->pcm = NULL;
1316 }
1317 if (pcm_open_retry_count-- == 0) {
1318 ret = -EIO;
1319 goto error_open;
1320 }
1321 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1322 continue;
1323 }
1324 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001325 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001326
1327 ALOGV("%s: pcm_prepare", __func__);
1328 ret = pcm_prepare(in->pcm);
1329 if (ret < 0) {
1330 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1331 pcm_close(in->pcm);
1332 in->pcm = NULL;
1333 goto error_open;
1334 }
1335
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301336 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001337 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001338
Eric Laurentc8400632013-02-14 19:04:54 -08001339 return ret;
1340
1341error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301342 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001343 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001344error_config:
1345 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301346 /*
1347 * sleep 50ms to allow sufficient time for kernel
1348 * drivers to recover incases like SSR.
1349 */
1350 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001351 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001352
1353 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001354}
1355
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001356void lock_input_stream(struct stream_in *in)
1357{
1358 pthread_mutex_lock(&in->pre_lock);
1359 pthread_mutex_lock(&in->lock);
1360 pthread_mutex_unlock(&in->pre_lock);
1361}
1362
1363void lock_output_stream(struct stream_out *out)
1364{
1365 pthread_mutex_lock(&out->pre_lock);
1366 pthread_mutex_lock(&out->lock);
1367 pthread_mutex_unlock(&out->pre_lock);
1368}
1369
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001370/* must be called with out->lock locked */
1371static int send_offload_cmd_l(struct stream_out* out, int command)
1372{
1373 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1374
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001375 if (!cmd) {
1376 ALOGE("failed to allocate mem for command 0x%x", command);
1377 return -ENOMEM;
1378 }
1379
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001380 ALOGVV("%s %d", __func__, command);
1381
1382 cmd->cmd = command;
1383 list_add_tail(&out->offload_cmd_list, &cmd->node);
1384 pthread_cond_signal(&out->offload_cond);
1385 return 0;
1386}
1387
1388/* must be called iwth out->lock locked */
1389static void stop_compressed_output_l(struct stream_out *out)
1390{
1391 out->offload_state = OFFLOAD_STATE_IDLE;
1392 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001393 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001394 if (out->compr != NULL) {
1395 compress_stop(out->compr);
1396 while (out->offload_thread_blocked) {
1397 pthread_cond_wait(&out->cond, &out->lock);
1398 }
1399 }
1400}
1401
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001402bool is_offload_usecase(audio_usecase_t uc_id)
1403{
1404 unsigned int i;
1405 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1406 if (uc_id == offload_usecases[i])
1407 return true;
1408 }
1409 return false;
1410}
1411
vivek mehta446c3962015-09-14 10:57:35 -07001412static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001413{
vivek mehta446c3962015-09-14 10:57:35 -07001414 audio_usecase_t ret_uc = USECASE_INVALID;
1415 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001416 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001417 if (!adev->multi_offload_enable) {
1418 if (is_direct_pcm)
1419 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1420 else
1421 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001422
vivek mehta446c3962015-09-14 10:57:35 -07001423 pthread_mutex_lock(&adev->lock);
1424 if (get_usecase_from_list(adev, ret_uc) != NULL)
1425 ret_uc = USECASE_INVALID;
1426 pthread_mutex_unlock(&adev->lock);
1427
1428 return ret_uc;
1429 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001430
1431 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001432 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1433 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1434 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1435 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001436 break;
1437 }
1438 }
vivek mehta446c3962015-09-14 10:57:35 -07001439
1440 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1441 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001442}
1443
1444static void free_offload_usecase(struct audio_device *adev,
1445 audio_usecase_t uc_id)
1446{
vivek mehta446c3962015-09-14 10:57:35 -07001447 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001448 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001449
1450 if (!adev->multi_offload_enable)
1451 return;
1452
1453 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1454 if (offload_usecases[offload_uc_index] == uc_id) {
1455 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001456 break;
1457 }
1458 }
1459 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1460}
1461
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001462static void *offload_thread_loop(void *context)
1463{
1464 struct stream_out *out = (struct stream_out *) context;
1465 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001466 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001467
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001468 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1469 set_sched_policy(0, SP_FOREGROUND);
1470 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1471
1472 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001473 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001474 for (;;) {
1475 struct offload_cmd *cmd = NULL;
1476 stream_callback_event_t event;
1477 bool send_callback = false;
1478
1479 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1480 __func__, list_empty(&out->offload_cmd_list),
1481 out->offload_state);
1482 if (list_empty(&out->offload_cmd_list)) {
1483 ALOGV("%s SLEEPING", __func__);
1484 pthread_cond_wait(&out->offload_cond, &out->lock);
1485 ALOGV("%s RUNNING", __func__);
1486 continue;
1487 }
1488
1489 item = list_head(&out->offload_cmd_list);
1490 cmd = node_to_item(item, struct offload_cmd, node);
1491 list_remove(item);
1492
1493 ALOGVV("%s STATE %d CMD %d out->compr %p",
1494 __func__, out->offload_state, cmd->cmd, out->compr);
1495
1496 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1497 free(cmd);
1498 break;
1499 }
1500
1501 if (out->compr == NULL) {
1502 ALOGE("%s: Compress handle is NULL", __func__);
1503 pthread_cond_signal(&out->cond);
1504 continue;
1505 }
1506 out->offload_thread_blocked = true;
1507 pthread_mutex_unlock(&out->lock);
1508 send_callback = false;
1509 switch(cmd->cmd) {
1510 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001511 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001512 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001513 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001514 send_callback = true;
1515 event = STREAM_CBK_EVENT_WRITE_READY;
1516 break;
1517 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001518 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301519 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001520 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301521 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001522 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301523 if (ret < 0)
1524 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301525 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301526 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001527 compress_drain(out->compr);
1528 else
1529 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301530 if (ret != -ENETRESET) {
1531 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301532 pthread_mutex_lock(&out->lock);
1533 out->send_new_metadata = 1;
1534 out->send_next_track_params = true;
1535 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301536 event = STREAM_CBK_EVENT_DRAIN_READY;
1537 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1538 } else
1539 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001540 break;
1541 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001542 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001543 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001544 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001545 send_callback = true;
1546 event = STREAM_CBK_EVENT_DRAIN_READY;
1547 break;
1548 default:
1549 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1550 break;
1551 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001552 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001553 out->offload_thread_blocked = false;
1554 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001555 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001556 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001557 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001558 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001559 free(cmd);
1560 }
1561
1562 pthread_cond_signal(&out->cond);
1563 while (!list_empty(&out->offload_cmd_list)) {
1564 item = list_head(&out->offload_cmd_list);
1565 list_remove(item);
1566 free(node_to_item(item, struct offload_cmd, node));
1567 }
1568 pthread_mutex_unlock(&out->lock);
1569
1570 return NULL;
1571}
1572
1573static int create_offload_callback_thread(struct stream_out *out)
1574{
1575 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1576 list_init(&out->offload_cmd_list);
1577 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1578 offload_thread_loop, out);
1579 return 0;
1580}
1581
1582static int destroy_offload_callback_thread(struct stream_out *out)
1583{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001584 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001585 stop_compressed_output_l(out);
1586 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1587
1588 pthread_mutex_unlock(&out->lock);
1589 pthread_join(out->offload_thread, (void **) NULL);
1590 pthread_cond_destroy(&out->offload_cond);
1591
1592 return 0;
1593}
1594
Mingming Yin21854652016-04-13 11:54:02 -07001595static bool allow_hdmi_channel_config(struct audio_device *adev,
1596 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001597{
1598 struct listnode *node;
1599 struct audio_usecase *usecase;
1600 bool ret = true;
1601
Mingming Yin21854652016-04-13 11:54:02 -07001602 if (enable_passthru && !audio_extn_passthru_is_enabled()) {
1603 ret = false;
1604 goto exit;
1605 }
1606
1607 if (audio_extn_passthru_is_active()) {
1608 ALOGI("%s: Compress audio passthrough is active,"
1609 "no HDMI config change allowed", __func__);
1610 ret = false;
1611 goto exit;
1612 }
1613
Eric Laurent07eeafd2013-10-06 12:52:49 -07001614 list_for_each(node, &adev->usecase_list) {
1615 usecase = node_to_item(node, struct audio_usecase, list);
1616 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1617 /*
1618 * If voice call is already existing, do not proceed further to avoid
1619 * disabling/enabling both RX and TX devices, CSD calls, etc.
1620 * Once the voice call done, the HDMI channels can be configured to
1621 * max channels of remaining use cases.
1622 */
1623 if (usecase->id == USECASE_VOICE_CALL) {
Mingming Yin21854652016-04-13 11:54:02 -07001624 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001625 __func__);
1626 ret = false;
1627 break;
1628 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Mingming Yin21854652016-04-13 11:54:02 -07001629 if (!enable_passthru) {
1630 ALOGV("%s: multi channel playback is active, "
1631 "no change in HDMI channels", __func__);
1632 ret = false;
1633 break;
1634 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001635 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001636 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin21854652016-04-13 11:54:02 -07001637 if (!enable_passthru) {
1638 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1639 ", no change in HDMI channels", __func__,
1640 usecase->stream.out->channel_mask);
1641 ret = false;
1642 break;
1643 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001644 }
1645 }
1646 }
Mingming Yin21854652016-04-13 11:54:02 -07001647 ALOGV("allow hdmi config %d", ret);
1648exit:
Eric Laurent07eeafd2013-10-06 12:52:49 -07001649 return ret;
1650}
1651
Mingming Yin21854652016-04-13 11:54:02 -07001652static int check_and_set_hdmi_config(struct audio_device *adev,
1653 uint32_t channels,
1654 uint32_t sample_rate,
1655 audio_format_t format,
1656 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001657{
1658 struct listnode *node;
1659 struct audio_usecase *usecase;
Mingming Yin21854652016-04-13 11:54:02 -07001660 int32_t factor = 1;
1661 bool config = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001662
Mingming Yin21854652016-04-13 11:54:02 -07001663 ALOGV("%s channels %d sample_rate %d format:%x enable_passthru:%d",
1664 __func__, channels, sample_rate, format, enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001665
Mingming Yin21854652016-04-13 11:54:02 -07001666 if (channels != adev->cur_hdmi_channels) {
1667 ALOGV("channel does not match current hdmi channels");
1668 config = true;
1669 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001670
Mingming Yin21854652016-04-13 11:54:02 -07001671 if (sample_rate != adev->cur_hdmi_sample_rate) {
1672 ALOGV("sample rate does not match current hdmi sample rate");
1673 config = true;
1674 }
1675
1676 if (format != adev->cur_hdmi_format) {
1677 ALOGV("format does not match current hdmi format");
1678 config = true;
1679 }
1680
1681 /* TBD - add check for bit width */
1682 if (!config) {
1683 ALOGV("No need to config hdmi");
Eric Laurent07eeafd2013-10-06 12:52:49 -07001684 return 0;
1685 }
1686
Mingming Yin21854652016-04-13 11:54:02 -07001687 if (enable_passthru &&
1688 (format == AUDIO_FORMAT_E_AC3)) {
1689 ALOGV("factor 4 for E_AC3 passthru");
1690 factor = 4;
1691 }
1692
1693 platform_set_hdmi_config(adev->platform, channels, factor * sample_rate,
1694 enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001695 adev->cur_hdmi_channels = channels;
Mingming Yin21854652016-04-13 11:54:02 -07001696 adev->cur_hdmi_format = format;
1697 adev->cur_hdmi_sample_rate = sample_rate;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001698
1699 /*
1700 * Deroute all the playback streams routed to HDMI so that
1701 * the back end is deactivated. Note that backend will not
1702 * be deactivated if any one stream is connected to it.
1703 */
1704 list_for_each(node, &adev->usecase_list) {
1705 usecase = node_to_item(node, struct audio_usecase, list);
1706 if (usecase->type == PCM_PLAYBACK &&
1707 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001708 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001709 }
1710 }
1711
Mingming Yin21854652016-04-13 11:54:02 -07001712 bool was_active = audio_extn_keep_alive_is_active();
1713 if (was_active)
1714 audio_extn_keep_alive_stop();
1715
Eric Laurent07eeafd2013-10-06 12:52:49 -07001716 /*
1717 * Enable all the streams disabled above. Now the HDMI backend
1718 * will be activated with new channel configuration
1719 */
1720 list_for_each(node, &adev->usecase_list) {
1721 usecase = node_to_item(node, struct audio_usecase, list);
1722 if (usecase->type == PCM_PLAYBACK &&
1723 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001724 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001725 }
1726 }
1727
Mingming Yin21854652016-04-13 11:54:02 -07001728 if (was_active)
1729 audio_extn_keep_alive_start();
1730
Eric Laurent07eeafd2013-10-06 12:52:49 -07001731 return 0;
1732}
1733
Mingming Yin21854652016-04-13 11:54:02 -07001734/* called with out lock taken */
1735static int check_and_set_hdmi_backend(struct stream_out *out)
1736{
1737 struct audio_device *adev = out->dev;
1738 int ret;
1739 bool enable_passthru = false;
1740
1741 if (!(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL))
1742 return -1;
1743
1744 ALOGV("%s usecase %s out->format:%x out->bit_width:%d", __func__, use_case_table[out->usecase],out->format,out->bit_width);
1745
1746 if (is_offload_usecase(out->usecase) &&
1747 audio_extn_dolby_is_passthrough_stream(out)) {
1748 enable_passthru = true;
1749 }
1750
1751 /* Check if change in HDMI channel config is allowed */
1752 if (!allow_hdmi_channel_config(adev, enable_passthru)) {
1753 return -EPERM;
1754 }
1755
1756 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1757 uint32_t channels;
1758 ALOGV("Offload usecase, enable passthru %d", enable_passthru);
1759
1760 if (enable_passthru) {
1761 audio_extn_passthru_on_start(out);
1762 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1763 }
1764
1765 /* For pass through case, the backend should be configured as stereo */
1766 channels = enable_passthru ? DEFAULT_HDMI_OUT_CHANNELS :
1767 out->compr_config.codec->ch_in;
1768
1769 ret = check_and_set_hdmi_config(adev, channels,
1770 out->sample_rate, out->format,
1771 enable_passthru);
1772 } else
1773 ret = check_and_set_hdmi_config(adev, out->config.channels,
1774 out->config.rate,
1775 out->format,
1776 false);
1777 return ret;
1778}
1779
1780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781static int stop_output_stream(struct stream_out *out)
1782{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301783 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784 struct audio_usecase *uc_info;
1785 struct audio_device *adev = out->dev;
1786
Eric Laurent994a6932013-07-17 11:51:42 -07001787 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001788 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789 uc_info = get_usecase_from_list(adev, out->usecase);
1790 if (uc_info == NULL) {
1791 ALOGE("%s: Could not find the usecase (%d) in the list",
1792 __func__, out->usecase);
1793 return -EINVAL;
1794 }
1795
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001796 if (is_offload_usecase(out->usecase) &&
Mingming Yin21854652016-04-13 11:54:02 -07001797 !(audio_extn_dolby_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001798 if (adev->visualizer_stop_output != NULL)
1799 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001800
1801 audio_extn_dts_remove_state_notifier_node(out->usecase);
1802
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001803 if (adev->offload_effects_stop_output != NULL)
1804 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1805 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001806
Eric Laurent150dbfe2013-02-27 14:31:02 -08001807 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001808 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001809
1810 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001811 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001813 list_remove(&uc_info->list);
1814 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001815
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001816 if (is_offload_usecase(out->usecase) &&
Mingming Yin21854652016-04-13 11:54:02 -07001817 (audio_extn_dolby_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001818 ALOGV("Disable passthrough , reset mixer to pcm");
1819 /* NO_PASSTHROUGH */
1820 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001821
1822 /* Must be called after removing the usecase from list */
1823 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1824 check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
1825 DEFAULT_HDMI_OUT_SAMPLE_RATE,
1826 DEFAULT_HDMI_OUT_FORMAT,
1827 false);
1828 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001829 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1830 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001831
Eric Laurent994a6932013-07-17 11:51:42 -07001832 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001833 return ret;
1834}
1835
1836int start_output_stream(struct stream_out *out)
1837{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001838 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839 struct audio_usecase *uc_info;
1840 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301841 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001842
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001843 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1844 ret = -EINVAL;
1845 goto error_config;
1846 }
1847
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301848 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1849 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1850 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301851
Naresh Tanniru80659832014-06-04 18:17:56 +05301852 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301853 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301854 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301855 goto error_config;
1856 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301857
Eric Laurentb23d5282013-05-14 15:27:20 -07001858 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001859 if (out->pcm_device_id < 0) {
1860 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1861 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001862 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001863 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864 }
1865
1866 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001867
1868 if (!uc_info) {
1869 ret = -ENOMEM;
1870 goto error_config;
1871 }
1872
Mingming Yin21854652016-04-13 11:54:02 -07001873 /* This must be called before adding this usecase to the list */
1874 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1875 /* This call can fail if compress pass thru is already active */
1876 check_and_set_hdmi_backend(out);
1877 }
1878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879 uc_info->id = out->usecase;
1880 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001881 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001882 uc_info->devices = out->devices;
1883 uc_info->in_snd_device = SND_DEVICE_NONE;
1884 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001885 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301887 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1888 adev->perf_lock_opts,
1889 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001890 select_devices(adev, out->usecase);
1891
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001892 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1893 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001894 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001895 unsigned int flags = PCM_OUT;
1896 unsigned int pcm_open_retry_count = 0;
1897 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1898 flags |= PCM_MMAP | PCM_NOIRQ;
1899 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1900 } else
1901 flags |= PCM_MONOTONIC;
1902
1903 while (1) {
1904 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1905 flags, &out->config);
1906 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1907 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1908 if (out->pcm != NULL) {
1909 pcm_close(out->pcm);
1910 out->pcm = NULL;
1911 }
1912 if (pcm_open_retry_count-- == 0) {
1913 ret = -EIO;
1914 goto error_open;
1915 }
1916 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1917 continue;
1918 }
1919 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001920 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001921
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001922 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1923 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001924
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001925 ALOGV("%s: pcm_prepare", __func__);
1926 if (pcm_is_ready(out->pcm)) {
1927 ret = pcm_prepare(out->pcm);
1928 if (ret < 0) {
1929 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1930 pcm_close(out->pcm);
1931 out->pcm = NULL;
1932 goto error_open;
1933 }
1934 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001935 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001936 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1937 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001938 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001939 out->compr = compress_open(adev->snd_card,
1940 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001941 COMPRESS_IN, &out->compr_config);
1942 if (out->compr && !is_compress_ready(out->compr)) {
1943 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1944 compress_close(out->compr);
1945 out->compr = NULL;
1946 ret = -EIO;
1947 goto error_open;
1948 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301949 /* compress_open sends params of the track, so reset the flag here */
1950 out->is_compr_metadata_avail = false;
1951
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001952 if (out->offload_callback)
1953 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001954
Fred Oh3f43e742015-03-04 18:42:34 -08001955 /* Since small bufs uses blocking writes, a write will be blocked
1956 for the default max poll time (20s) in the event of an SSR.
1957 Reduce the poll time to observe and deal with SSR faster.
1958 */
1959 if (out->use_small_bufs) {
1960 compress_set_max_poll_wait(out->compr, 1000);
1961 }
1962
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001963 audio_extn_dts_create_state_notifier_node(out->usecase);
1964 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1965 popcount(out->channel_mask),
1966 out->playback_started);
1967
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001968#ifdef DS1_DOLBY_DDP_ENABLED
1969 if (audio_extn_is_dolby_format(out->format))
1970 audio_extn_dolby_send_ddp_endp_params(adev);
1971#endif
Mingming Yin21854652016-04-13 11:54:02 -07001972 if (!(audio_extn_dolby_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001973 if (adev->visualizer_start_output != NULL)
1974 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1975 if (adev->offload_effects_start_output != NULL)
1976 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001977 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001978 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301980 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001981 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001984error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301985 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001987error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301988 /*
1989 * sleep 50ms to allow sufficient time for kernel
1990 * drivers to recover incases like SSR.
1991 */
1992 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001993 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001994}
1995
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996static int check_input_parameters(uint32_t sample_rate,
1997 audio_format_t format,
1998 int channel_count)
1999{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002000 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302002 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2003 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2004 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002005 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302006 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002007
2008 switch (channel_count) {
2009 case 1:
2010 case 2:
2011 case 6:
2012 break;
2013 default:
2014 ret = -EINVAL;
2015 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016
2017 switch (sample_rate) {
2018 case 8000:
2019 case 11025:
2020 case 12000:
2021 case 16000:
2022 case 22050:
2023 case 24000:
2024 case 32000:
2025 case 44100:
2026 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302027 case 96000:
2028 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029 break;
2030 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002031 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032 }
2033
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002034 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002035}
2036
2037static size_t get_input_buffer_size(uint32_t sample_rate,
2038 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002039 int channel_count,
2040 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041{
2042 size_t size = 0;
2043
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002044 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2045 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002046
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002047 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002048 if (is_low_latency)
2049 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302050
2051 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002053 /* make sure the size is multiple of 32 bytes
2054 * At 48 kHz mono 16-bit PCM:
2055 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2056 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2057 */
2058 size += 0x1f;
2059 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002060
2061 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002062}
2063
2064static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2065{
2066 struct stream_out *out = (struct stream_out *)stream;
2067
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002068 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002069}
2070
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002071static int out_set_sample_rate(struct audio_stream *stream __unused,
2072 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002073{
2074 return -ENOSYS;
2075}
2076
2077static size_t out_get_buffer_size(const struct audio_stream *stream)
2078{
2079 struct stream_out *out = (struct stream_out *)stream;
2080
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002081 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002082 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002083 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2084 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002085
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002086 return out->config.period_size *
2087 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002088}
2089
2090static uint32_t out_get_channels(const struct audio_stream *stream)
2091{
2092 struct stream_out *out = (struct stream_out *)stream;
2093
2094 return out->channel_mask;
2095}
2096
2097static audio_format_t out_get_format(const struct audio_stream *stream)
2098{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002099 struct stream_out *out = (struct stream_out *)stream;
2100
2101 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102}
2103
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002104static int out_set_format(struct audio_stream *stream __unused,
2105 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106{
2107 return -ENOSYS;
2108}
2109
2110static int out_standby(struct audio_stream *stream)
2111{
2112 struct stream_out *out = (struct stream_out *)stream;
2113 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002114
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302115 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2116 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002117 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2118 /* Ignore standby in case of voip call because the voip output
2119 * stream is closed in adev_close_output_stream()
2120 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302121 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002122 return 0;
2123 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002125 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002126 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002127 if (adev->adm_deregister_stream)
2128 adev->adm_deregister_stream(adev->adm_data, out->handle);
2129
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002130 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002132 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002133 if (out->pcm) {
2134 pcm_close(out->pcm);
2135 out->pcm = NULL;
2136 }
2137 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002138 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002139 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302140 out->send_next_track_params = false;
2141 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002142 out->gapless_mdata.encoder_delay = 0;
2143 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002144 if (out->compr != NULL) {
2145 compress_close(out->compr);
2146 out->compr = NULL;
2147 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002148 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002150 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 }
2152 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302153 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002154 return 0;
2155}
2156
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002157static int out_dump(const struct audio_stream *stream __unused,
2158 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002159{
2160 return 0;
2161}
2162
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002163static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2164{
2165 int ret = 0;
2166 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002167
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002168 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002169 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002170 return -EINVAL;
2171 }
2172
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302173 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002174
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002175 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2176 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302177 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002178 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002179 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2180 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302181 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002182 }
2183
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002184 ALOGV("%s new encoder delay %u and padding %u", __func__,
2185 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2186
2187 return 0;
2188}
2189
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002190static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2191{
2192 return out == adev->primary_output || out == adev->voice_tx_output;
2193}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2196{
2197 struct stream_out *out = (struct stream_out *)stream;
2198 struct audio_device *adev = out->dev;
2199 struct str_parms *parms;
2200 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002201 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002202
sangwoobc677242013-08-08 16:53:43 +09002203 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002204 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002205 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302206 if (!parms)
2207 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002208 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2209 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002211 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002212 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002213
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002214 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302215 * When HDMI cable is unplugged/usb hs is disconnected the
2216 * music playback is paused and the policy manager sends routing=0
2217 * But the audioflingercontinues to write data until standby time
2218 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002219 * Avoid this by routing audio to speaker until standby.
2220 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302221 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2222 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002223 val == AUDIO_DEVICE_NONE) {
Mingming Yin21854652016-04-13 11:54:02 -07002224 if (!audio_extn_dolby_is_passthrough_stream(out))
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08002225 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002226 }
2227
2228 /*
2229 * select_devices() call below switches all the usecases on the same
2230 * backend to the new device. Refer to check_usecases_codec_backend() in
2231 * the select_devices(). But how do we undo this?
2232 *
2233 * For example, music playback is active on headset (deep-buffer usecase)
2234 * and if we go to ringtones and select a ringtone, low-latency usecase
2235 * will be started on headset+speaker. As we can't enable headset+speaker
2236 * and headset devices at the same time, select_devices() switches the music
2237 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2238 * So when the ringtone playback is completed, how do we undo the same?
2239 *
2240 * We are relying on the out_set_parameters() call on deep-buffer output,
2241 * once the ringtone playback is ended.
2242 * NOTE: We should not check if the current devices are same as new devices.
2243 * Because select_devices() must be called to switch back the music
2244 * playback to headset.
2245 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002246 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002247 out->devices = val;
2248
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302249 if (!out->standby) {
2250 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2251 adev->perf_lock_opts,
2252 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002253 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302254 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2255 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002256
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002257 if (output_drives_call(adev, out)) {
2258 if(!voice_is_in_call(adev)) {
2259 if (adev->mode == AUDIO_MODE_IN_CALL) {
2260 adev->current_call_output = out;
2261 ret = voice_start_call(adev);
2262 }
2263 } else {
2264 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002265 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002266 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002267 }
2268 }
2269
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002271 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002272 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002273
2274 if (out == adev->primary_output) {
2275 pthread_mutex_lock(&adev->lock);
2276 audio_extn_set_parameters(adev, parms);
2277 pthread_mutex_unlock(&adev->lock);
2278 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002279 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002280 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002281 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002282
2283 audio_extn_dts_create_state_notifier_node(out->usecase);
2284 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2285 popcount(out->channel_mask),
2286 out->playback_started);
2287
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002288 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002289 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002291 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302292error:
Eric Laurent994a6932013-07-17 11:51:42 -07002293 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294 return ret;
2295}
2296
2297static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2298{
2299 struct stream_out *out = (struct stream_out *)stream;
2300 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002301 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002302 char value[256];
2303 struct str_parms *reply = str_parms_create();
2304 size_t i, j;
2305 int ret;
2306 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002307
2308 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002309 if (reply) {
2310 str_parms_destroy(reply);
2311 }
2312 if (query) {
2313 str_parms_destroy(query);
2314 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002315 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2316 return NULL;
2317 }
2318
Eric Laurent994a6932013-07-17 11:51:42 -07002319 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2321 if (ret >= 0) {
2322 value[0] = '\0';
2323 i = 0;
2324 while (out->supported_channel_masks[i] != 0) {
2325 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2326 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2327 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002328 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002329 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002330 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002331 first = false;
2332 break;
2333 }
2334 }
2335 i++;
2336 }
2337 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2338 str = str_parms_to_str(reply);
2339 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002340 voice_extn_out_get_parameters(out, query, reply);
2341 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002342 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002343 free(str);
2344 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002345 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002347
Alexy Joseph62142aa2015-11-16 15:10:34 -08002348
2349 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2350 if (ret >= 0) {
2351 value[0] = '\0';
2352 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2353 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302354 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002355 } else {
2356 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302357 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002358 }
2359 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002360 if (str)
2361 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002362 str = str_parms_to_str(reply);
2363 }
2364
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002365 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2366 if (ret >= 0) {
2367 value[0] = '\0';
2368 i = 0;
2369 first = true;
2370 while (out->supported_formats[i] != 0) {
2371 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2372 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2373 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002374 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002375 }
2376 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2377 first = false;
2378 break;
2379 }
2380 }
2381 i++;
2382 }
2383 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002384 if (str)
2385 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002386 str = str_parms_to_str(reply);
2387 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002388
2389 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2390 if (ret >= 0) {
2391 value[0] = '\0';
2392 i = 0;
2393 first = true;
2394 while (out->supported_sample_rates[i] != 0) {
2395 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2396 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2397 if (!first) {
2398 strlcat(value, "|", sizeof(value));
2399 }
2400 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2401 first = false;
2402 break;
2403 }
2404 }
2405 i++;
2406 }
2407 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2408 if (str)
2409 free(str);
2410 str = str_parms_to_str(reply);
2411 }
2412
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002413 str_parms_destroy(query);
2414 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002415 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002416 return str;
2417}
2418
2419static uint32_t out_get_latency(const struct audio_stream_out *stream)
2420{
2421 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002422 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002423
Alexy Josephaa54c872014-12-03 02:46:47 -08002424 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002425 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002426 } else {
2427 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002428 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002429 }
2430
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302431 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002432 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433}
2434
2435static int out_set_volume(struct audio_stream_out *stream, float left,
2436 float right)
2437{
Eric Laurenta9024de2013-04-04 09:19:12 -07002438 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002439 int volume[2];
2440
Eric Laurenta9024de2013-04-04 09:19:12 -07002441 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2442 /* only take left channel into account: the API is for stereo anyway */
2443 out->muted = (left == 0.0f);
2444 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002445 } else if (is_offload_usecase(out->usecase)) {
Mingming Yin21854652016-04-13 11:54:02 -07002446 if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002447 /*
2448 * Set mute or umute on HDMI passthrough stream.
2449 * Only take left channel into account.
2450 * Mute is 0 and unmute 1
2451 */
2452 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2453 } else {
2454 char mixer_ctl_name[128];
2455 struct audio_device *adev = out->dev;
2456 struct mixer_ctl *ctl;
2457 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002458 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002459
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002460 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2461 "Compress Playback %d Volume", pcm_device_id);
2462 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2463 if (!ctl) {
2464 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2465 __func__, mixer_ctl_name);
2466 return -EINVAL;
2467 }
2468 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2469 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2470 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2471 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002472 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002473 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002474
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475 return -ENOSYS;
2476}
2477
2478static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2479 size_t bytes)
2480{
2481 struct stream_out *out = (struct stream_out *)stream;
2482 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302483 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002484 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002486 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302487
Naresh Tanniru80659832014-06-04 18:17:56 +05302488 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002489
Ashish Jainbbce4322016-02-16 13:25:27 +05302490 if (is_offload_usecase(out->usecase)) {
2491 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302492 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2493 pthread_mutex_unlock(&out->lock);
2494 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302495 } else {
2496 /* increase written size during SSR to avoid mismatch
2497 * with the written frames count in AF
2498 */
2499 out->written += bytes / (out->config.channels * sizeof(short));
2500 ALOGD(" %s: sound card is not active/SSR state", __func__);
2501 ret= -EIO;
2502 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302503 }
2504 }
2505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002507 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002508 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002509 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2510 ret = voice_extn_compress_voip_start_output_stream(out);
2511 else
2512 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002513 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002514 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002516 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517 goto exit;
2518 }
vivek mehta446c3962015-09-14 10:57:35 -07002519 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002520 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522
Ashish Jain81eb2a82015-05-13 10:52:34 +05302523 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002524 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302525 adev->is_channel_status_set = true;
2526 }
2527
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002528 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002529 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002530 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002531 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002532 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2533 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302534 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2535 ALOGD("copl(%p):send next track params in gapless", out);
2536 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2537 out->send_next_track_params = false;
2538 out->is_compr_metadata_avail = false;
2539 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002540 }
2541
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002542 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302543 if (ret < 0)
2544 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302545 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002546 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302547 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002548 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302549 } else if (-ENETRESET == ret) {
2550 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2551 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2552 pthread_mutex_unlock(&out->lock);
2553 out_standby(&out->stream.common);
2554 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002555 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302556 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002557 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002558 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002559 out->playback_started = 1;
2560 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002561
2562 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2563 popcount(out->channel_mask),
2564 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002565 }
2566 pthread_mutex_unlock(&out->lock);
2567 return ret;
2568 } else {
2569 if (out->pcm) {
2570 if (out->muted)
2571 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002572
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302573 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002574
2575 if (adev->adm_request_focus)
2576 adev->adm_request_focus(adev->adm_data, out->handle);
2577
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002578 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2579 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2580 else
2581 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002582
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302583 if (ret < 0)
2584 ret = -errno;
2585 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002586 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002587
2588 if (adev->adm_abandon_focus)
2589 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002590 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591 }
2592
2593exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302594 /* ToDo: There may be a corner case when SSR happens back to back during
2595 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302596 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302597 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302598 }
2599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600 pthread_mutex_unlock(&out->lock);
2601
2602 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002603 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002604 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302605 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302606 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302607 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302608 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302609 out->standby = true;
2610 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302612 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302613 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614 }
2615 return bytes;
2616}
2617
2618static int out_get_render_position(const struct audio_stream_out *stream,
2619 uint32_t *dsp_frames)
2620{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002621 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302622 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002623
2624 if (dsp_frames == NULL)
2625 return -EINVAL;
2626
2627 *dsp_frames = 0;
2628 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002629 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002630 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002631 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302632 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002633 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302634 if (ret < 0)
2635 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002636 ALOGVV("%s rendered frames %d sample_rate %d",
2637 __func__, *dsp_frames, out->sample_rate);
2638 }
2639 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302640 if (-ENETRESET == ret) {
2641 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2642 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2643 return -EINVAL;
2644 } else if(ret < 0) {
2645 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2646 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302647 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2648 /*
2649 * Handle corner case where compress session is closed during SSR
2650 * and timestamp is queried
2651 */
2652 ALOGE(" ERROR: sound card not active, return error");
2653 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302654 } else {
2655 return 0;
2656 }
Zhou Song32a556e2015-05-05 10:46:56 +08002657 } else if (audio_is_linear_pcm(out->format)) {
2658 *dsp_frames = out->written;
2659 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002660 } else
2661 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662}
2663
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002664static int out_add_audio_effect(const struct audio_stream *stream __unused,
2665 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666{
2667 return 0;
2668}
2669
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002670static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2671 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002672{
2673 return 0;
2674}
2675
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002676static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2677 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002678{
2679 return -EINVAL;
2680}
2681
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002682static int out_get_presentation_position(const struct audio_stream_out *stream,
2683 uint64_t *frames, struct timespec *timestamp)
2684{
2685 struct stream_out *out = (struct stream_out *)stream;
2686 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002687 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002688
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002689 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002690
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002691 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002692 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302693 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002694 &out->sample_rate);
2695 ALOGVV("%s rendered frames %ld sample_rate %d",
2696 __func__, dsp_frames, out->sample_rate);
2697 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302698 if (ret < 0)
2699 ret = -errno;
2700 if (-ENETRESET == ret) {
2701 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2702 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2703 ret = -EINVAL;
2704 } else
2705 ret = 0;
2706
Eric Laurent949a0892013-09-20 09:20:13 -07002707 /* this is the best we can do */
2708 clock_gettime(CLOCK_MONOTONIC, timestamp);
2709 }
2710 } else {
2711 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002712 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002713 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2714 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002715 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002716 // This adjustment accounts for buffering after app processor.
2717 // It is based on estimated DSP latency per use case, rather than exact.
2718 signed_frames -=
2719 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2720
Eric Laurent949a0892013-09-20 09:20:13 -07002721 // It would be unusual for this value to be negative, but check just in case ...
2722 if (signed_frames >= 0) {
2723 *frames = signed_frames;
2724 ret = 0;
2725 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002726 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302727 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2728 *frames = out->written;
2729 clock_gettime(CLOCK_MONOTONIC, timestamp);
2730 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002731 }
2732 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002733 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002734 return ret;
2735}
2736
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002737static int out_set_callback(struct audio_stream_out *stream,
2738 stream_callback_t callback, void *cookie)
2739{
2740 struct stream_out *out = (struct stream_out *)stream;
2741
2742 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002743 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002744 out->offload_callback = callback;
2745 out->offload_cookie = cookie;
2746 pthread_mutex_unlock(&out->lock);
2747 return 0;
2748}
2749
2750static int out_pause(struct audio_stream_out* stream)
2751{
2752 struct stream_out *out = (struct stream_out *)stream;
2753 int status = -ENOSYS;
2754 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002755 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002756 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002757 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002758 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302759 struct audio_device *adev = out->dev;
2760 int snd_scard_state = get_snd_card_state(adev);
2761
2762 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2763 status = compress_pause(out->compr);
2764
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002765 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002766
Mingming Yin21854652016-04-13 11:54:02 -07002767 if (audio_extn_passthru_is_active()) {
2768 ALOGV("offload use case, pause passthru");
2769 audio_extn_passthru_on_pause(out);
2770 }
2771
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302772 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002773 audio_extn_dts_notify_playback_state(out->usecase, 0,
2774 out->sample_rate, popcount(out->channel_mask),
2775 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002776 }
2777 pthread_mutex_unlock(&out->lock);
2778 }
2779 return status;
2780}
2781
2782static int out_resume(struct audio_stream_out* stream)
2783{
2784 struct stream_out *out = (struct stream_out *)stream;
2785 int status = -ENOSYS;
2786 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002787 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002788 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002789 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002790 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002791 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302792 struct audio_device *adev = out->dev;
2793 int snd_scard_state = get_snd_card_state(adev);
2794
Mingming Yin21854652016-04-13 11:54:02 -07002795 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
2796 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2797 pthread_mutex_lock(&out->dev->lock);
2798 ALOGV("offload resume, check and set hdmi backend again");
2799 check_and_set_hdmi_backend(out);
2800 pthread_mutex_unlock(&out->dev->lock);
2801 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302802 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07002803 }
2804 if (!status) {
2805 out->offload_state = OFFLOAD_STATE_PLAYING;
2806 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302807 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002808 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2809 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002810 }
2811 pthread_mutex_unlock(&out->lock);
2812 }
2813 return status;
2814}
2815
2816static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2817{
2818 struct stream_out *out = (struct stream_out *)stream;
2819 int status = -ENOSYS;
2820 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002821 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002822 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002823 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2824 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2825 else
2826 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2827 pthread_mutex_unlock(&out->lock);
2828 }
2829 return status;
2830}
2831
2832static int out_flush(struct audio_stream_out* stream)
2833{
2834 struct stream_out *out = (struct stream_out *)stream;
2835 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002836 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002837 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002838 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002839 stop_compressed_output_l(out);
2840 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002841 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002842 return 0;
2843 }
2844 return -ENOSYS;
2845}
2846
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847/** audio_stream_in implementation **/
2848static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2849{
2850 struct stream_in *in = (struct stream_in *)stream;
2851
2852 return in->config.rate;
2853}
2854
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002855static int in_set_sample_rate(struct audio_stream *stream __unused,
2856 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857{
2858 return -ENOSYS;
2859}
2860
2861static size_t in_get_buffer_size(const struct audio_stream *stream)
2862{
2863 struct stream_in *in = (struct stream_in *)stream;
2864
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002865 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2866 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002867 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2868 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002869
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002870 return in->config.period_size *
2871 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002872}
2873
2874static uint32_t in_get_channels(const struct audio_stream *stream)
2875{
2876 struct stream_in *in = (struct stream_in *)stream;
2877
2878 return in->channel_mask;
2879}
2880
2881static audio_format_t in_get_format(const struct audio_stream *stream)
2882{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002883 struct stream_in *in = (struct stream_in *)stream;
2884
2885 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002886}
2887
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002888static int in_set_format(struct audio_stream *stream __unused,
2889 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002890{
2891 return -ENOSYS;
2892}
2893
2894static int in_standby(struct audio_stream *stream)
2895{
2896 struct stream_in *in = (struct stream_in *)stream;
2897 struct audio_device *adev = in->dev;
2898 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302899 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2900 stream, in->usecase, use_case_table[in->usecase]);
2901
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002902 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2903 /* Ignore standby in case of voip call because the voip input
2904 * stream is closed in adev_close_input_stream()
2905 */
2906 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2907 return status;
2908 }
2909
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002910 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002911 if (!in->standby && in->is_st_session) {
2912 ALOGD("%s: sound trigger pcm stop lab", __func__);
2913 audio_extn_sound_trigger_stop_lab(in);
2914 in->standby = 1;
2915 }
2916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002918 if (adev->adm_deregister_stream)
2919 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2920
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002921 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002923 if (in->pcm) {
2924 pcm_close(in->pcm);
2925 in->pcm = NULL;
2926 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002927 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002928 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002929 }
2930 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002931 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002932 return status;
2933}
2934
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002935static int in_dump(const struct audio_stream *stream __unused,
2936 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002937{
2938 return 0;
2939}
2940
2941static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2942{
2943 struct stream_in *in = (struct stream_in *)stream;
2944 struct audio_device *adev = in->dev;
2945 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002947 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002948
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302949 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002950 parms = str_parms_create_str(kvpairs);
2951
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302952 if (!parms)
2953 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002954 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002955 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002956
2957 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2958 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002959 val = atoi(value);
2960 /* no audio source uses val == 0 */
2961 if ((in->source != val) && (val != 0)) {
2962 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002963 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2964 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2965 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08002966 (in->config.rate == 8000 || in->config.rate == 16000 ||
2967 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002968 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002969 err = voice_extn_compress_voip_open_input_stream(in);
2970 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002971 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002972 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002973 }
2974 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002975 }
2976 }
2977
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002978 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2979 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002981 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982 in->device = val;
2983 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002984 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002985 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986 }
2987 }
2988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002990 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002991
2992 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302993error:
Eric Laurent994a6932013-07-17 11:51:42 -07002994 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 return ret;
2996}
2997
2998static char* in_get_parameters(const struct audio_stream *stream,
2999 const char *keys)
3000{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003001 struct stream_in *in = (struct stream_in *)stream;
3002 struct str_parms *query = str_parms_create_str(keys);
3003 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003004 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003005
3006 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003007 if (reply) {
3008 str_parms_destroy(reply);
3009 }
3010 if (query) {
3011 str_parms_destroy(query);
3012 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003013 ALOGE("in_get_parameters: failed to create query or reply");
3014 return NULL;
3015 }
3016
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003017 ALOGV("%s: enter: keys - %s", __func__, keys);
3018
3019 voice_extn_in_get_parameters(in, query, reply);
3020
3021 str = str_parms_to_str(reply);
3022 str_parms_destroy(query);
3023 str_parms_destroy(reply);
3024
3025 ALOGV("%s: exit: returns - %s", __func__, str);
3026 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027}
3028
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003029static int in_set_gain(struct audio_stream_in *stream __unused,
3030 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031{
3032 return 0;
3033}
3034
3035static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3036 size_t bytes)
3037{
3038 struct stream_in *in = (struct stream_in *)stream;
3039 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303040 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303041 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303042 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003044 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303045
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003046 if (in->is_st_session) {
3047 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3048 /* Read from sound trigger HAL */
3049 audio_extn_sound_trigger_read(in, buffer, bytes);
3050 pthread_mutex_unlock(&in->lock);
3051 return bytes;
3052 }
3053
Ashish Jainbbce4322016-02-16 13:25:27 +05303054 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003055 ALOGD(" %s: sound card is not active/SSR state", __func__);
3056 ret= -EIO;;
3057 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303058 }
3059
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003061 pthread_mutex_lock(&adev->lock);
3062 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3063 ret = voice_extn_compress_voip_start_input_stream(in);
3064 else
3065 ret = start_input_stream(in);
3066 pthread_mutex_unlock(&adev->lock);
3067 if (ret != 0) {
3068 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069 }
3070 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003071 if (adev->adm_register_input_stream)
3072 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003075 if (adev->adm_request_focus)
3076 adev->adm_request_focus(adev->adm_data, in->capture_handle);
3077
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303079 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003080 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303081 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003082 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303083 } else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003084 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303085 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003086 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303087 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3088 if (bytes % 4 == 0) {
3089 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3090 int_buf_stream = buffer;
3091 for (size_t itt=0; itt < bytes/4 ; itt++) {
3092 int_buf_stream[itt] >>= 8;
3093 }
3094 } else {
3095 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3096 ret = -EINVAL;
3097 goto exit;
3098 }
3099 } if (ret < 0) {
3100 ret = -errno;
3101 }
3102 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003103 }
3104
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003105 if (adev->adm_abandon_focus)
3106 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
3107
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003108 /*
3109 * Instead of writing zeroes here, we could trust the hardware
3110 * to always provide zeroes when muted.
3111 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303112 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3113 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114 memset(buffer, 0, bytes);
3115
3116exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303117 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303118 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003119 if (-ENETRESET == ret)
3120 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122 pthread_mutex_unlock(&in->lock);
3123
3124 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303125 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303126 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303127 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303128 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303129 in->standby = true;
3130 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303131 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003133 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303134 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303135 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136 }
3137 return bytes;
3138}
3139
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003140static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141{
3142 return 0;
3143}
3144
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003145static int add_remove_audio_effect(const struct audio_stream *stream,
3146 effect_handle_t effect,
3147 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003149 struct stream_in *in = (struct stream_in *)stream;
3150 int status = 0;
3151 effect_descriptor_t desc;
3152
3153 status = (*effect)->get_descriptor(effect, &desc);
3154 if (status != 0)
3155 return status;
3156
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003157 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003158 pthread_mutex_lock(&in->dev->lock);
3159 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3160 in->enable_aec != enable &&
3161 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3162 in->enable_aec = enable;
3163 if (!in->standby)
3164 select_devices(in->dev, in->usecase);
3165 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003166 if (in->enable_ns != enable &&
3167 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3168 in->enable_ns = enable;
3169 if (!in->standby)
3170 select_devices(in->dev, in->usecase);
3171 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003172 pthread_mutex_unlock(&in->dev->lock);
3173 pthread_mutex_unlock(&in->lock);
3174
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175 return 0;
3176}
3177
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003178static int in_add_audio_effect(const struct audio_stream *stream,
3179 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180{
Eric Laurent994a6932013-07-17 11:51:42 -07003181 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003182 return add_remove_audio_effect(stream, effect, true);
3183}
3184
3185static int in_remove_audio_effect(const struct audio_stream *stream,
3186 effect_handle_t effect)
3187{
Eric Laurent994a6932013-07-17 11:51:42 -07003188 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003189 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190}
3191
3192static int adev_open_output_stream(struct audio_hw_device *dev,
3193 audio_io_handle_t handle,
3194 audio_devices_t devices,
3195 audio_output_flags_t flags,
3196 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003197 struct audio_stream_out **stream_out,
3198 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199{
3200 struct audio_device *adev = (struct audio_device *)dev;
3201 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303202 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003203 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003205 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303206
3207 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3208 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003209 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303210 return -EINVAL;
3211 }
3212
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3214
Mingming Yin3a941d42016-02-17 18:08:05 -08003215 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3216 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303217 devices, flags, &out->stream);
3218
3219
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003220 if (!out) {
3221 return -ENOMEM;
3222 }
3223
Haynes Mathew George204045b2015-02-25 20:32:03 -08003224 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003225 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003226 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003228 if (devices == AUDIO_DEVICE_NONE)
3229 devices = AUDIO_DEVICE_OUT_SPEAKER;
3230
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003231 out->flags = flags;
3232 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003233 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003234 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003235 out->sample_rate = config->sample_rate;
3236 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3237 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003238 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003239 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003240 out->non_blocking = 0;
3241 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003242
Mingming Yin3a941d42016-02-17 18:08:05 -08003243 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3244 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3245 pthread_mutex_lock(&adev->lock);
3246 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3247 ret = read_hdmi_sink_caps(out);
3248 pthread_mutex_unlock(&adev->lock);
3249 if (ret != 0) {
3250 if (ret == -ENOSYS) {
3251 /* ignore and go with default */
3252 ret = 0;
3253 } else {
3254 ALOGE("error reading hdmi sink caps");
3255 goto error_open;
3256 }
3257 }
3258 }
3259
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003261 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303262 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3263 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003264 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3265 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3266
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003267 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003268 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3269 /*
3270 * Do not handle stereo output in Multi-channel cases
3271 * Stereo case is handled in normal playback path
3272 */
3273 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3274 ret = AUDIO_CHANNEL_OUT_STEREO;
3275 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003276
3277 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3278 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003279 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003280 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003281 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003282
3283 if (config->sample_rate == 0)
3284 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3285 if (config->channel_mask == 0)
3286 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003287 if (config->format == 0)
3288 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003289
3290 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003291 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003292 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3294 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003296 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003297 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003298 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3299 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003300 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003301 ret = voice_extn_compress_voip_open_output_stream(out);
3302 if (ret != 0) {
3303 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3304 __func__, ret);
3305 goto error_open;
3306 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003307 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3308 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3309
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003310 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3311 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3312 ALOGE("%s: Unsupported Offload information", __func__);
3313 ret = -EINVAL;
3314 goto error_open;
3315 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003316
Mingming Yin3a941d42016-02-17 18:08:05 -08003317 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003318 if(config->offload_info.format == 0)
3319 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003320 if (config->offload_info.sample_rate == 0)
3321 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003322 }
3323
Mingming Yin90310102013-11-13 16:57:00 -08003324 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003325 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003326 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003327 ret = -EINVAL;
3328 goto error_open;
3329 }
3330
3331 out->compr_config.codec = (struct snd_codec *)
3332 calloc(1, sizeof(struct snd_codec));
3333
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003334 if (!out->compr_config.codec) {
3335 ret = -ENOMEM;
3336 goto error_open;
3337 }
3338
vivek mehta0ea887a2015-08-26 14:01:20 -07003339 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003340 out->usecase = get_offload_usecase(adev, true);
3341 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003342 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003343 out->stream.set_callback = out_set_callback;
3344 out->stream.pause = out_pause;
3345 out->stream.resume = out_resume;
3346 out->stream.drain = out_drain;
3347 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003348 out->usecase = get_offload_usecase(adev, false);
3349 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003350 }
vivek mehta446c3962015-09-14 10:57:35 -07003351
3352 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003353 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3354 config->format == 0 && config->sample_rate == 0 &&
3355 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003356 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003357 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3358 } else {
3359 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3360 ret = -EEXIST;
3361 goto error_open;
3362 }
vivek mehta446c3962015-09-14 10:57:35 -07003363 }
3364
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003365 if (config->offload_info.channel_mask)
3366 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003367 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003368 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003369 config->offload_info.channel_mask = config->channel_mask;
3370 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003371 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003372 out->sample_rate = config->offload_info.sample_rate;
3373
Mingming Yin3ee55c62014-08-04 14:23:35 -07003374 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003375
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003376 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003377 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003378 audio_extn_dolby_get_snd_codec_id(adev, out,
3379 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003380 else
3381 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003382 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003383
3384 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3385 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003386 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003387 platform_get_pcm_offload_buffer_size(&config->offload_info);
Mingming Yin21854652016-04-13 11:54:02 -07003388 } else if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003389 out->compr_config.fragment_size =
3390 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003391 } else {
3392 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003393 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003394 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003395 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3396 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003397 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003398 out->compr_config.codec->bit_rate =
3399 config->offload_info.bit_rate;
3400 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003401 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003402 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303403 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003404 /*TODO: Do we need to change it for passthrough */
3405 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003406
Manish Dewangana6fc5442015-08-24 20:30:31 +05303407 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3408 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3409 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3410 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003411 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3412 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003413 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003414 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003415 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3416 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003417
Mingming Yin3ee55c62014-08-04 14:23:35 -07003418 if (out->bit_width == 24) {
3419 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3420 }
3421
Amit Shekhar6f461b12014-08-01 14:52:58 -07003422 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303423 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003424
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003425 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3426 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003427
Mingming Yin497419f2015-07-01 16:57:32 -07003428 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003429 //this flag is set from framework only if its for PCM formats
3430 //no need to check for PCM format again
3431 out->non_blocking = 0;
3432 out->use_small_bufs = true;
3433 ALOGI("Keep write blocking for small buff: non_blockling %d",
3434 out->non_blocking);
3435 }
3436
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003437 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303438 out->send_next_track_params = false;
3439 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003440 out->offload_state = OFFLOAD_STATE_IDLE;
3441 out->playback_started = 0;
3442
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003443 audio_extn_dts_create_state_notifier_node(out->usecase);
3444
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003445 create_offload_callback_thread(out);
3446 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3447 __func__, config->offload_info.version,
3448 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003449 //Decide if we need to use gapless mode by default
Mingming Yin21854652016-04-13 11:54:02 -07003450 if (!audio_extn_dolby_is_passthrough_stream(out)) {
3451 ALOGV("%s: don't enable gapless for passthrough", __func__);
3452 check_and_set_gapless_mode(adev);
3453 }
3454
3455 if (audio_extn_dolby_is_passthrough_stream(out)) {
3456 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3457 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003458 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303459 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003460 if (ret != 0) {
3461 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3462 __func__, ret);
3463 goto error_open;
3464 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003465 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3466 if (config->sample_rate == 0)
3467 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3468 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3469 config->sample_rate != 8000) {
3470 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3471 ret = -EINVAL;
3472 goto error_open;
3473 }
3474 out->sample_rate = config->sample_rate;
3475 out->config.rate = config->sample_rate;
3476 if (config->format == AUDIO_FORMAT_DEFAULT)
3477 config->format = AUDIO_FORMAT_PCM_16_BIT;
3478 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3479 config->format = AUDIO_FORMAT_PCM_16_BIT;
3480 ret = -EINVAL;
3481 goto error_open;
3482 }
3483 out->format = config->format;
3484 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3485 out->config = pcm_config_afe_proxy_playback;
3486 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003487 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3488 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3489 out->config = pcm_config_low_latency;
3490 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003491 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003492 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003493 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3494 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003495 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003496 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3497 format = AUDIO_FORMAT_PCM_16_BIT;
3498 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3499 out->config = pcm_config_deep_buffer;
3500 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003501 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003502 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003503 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003504 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003505 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003506 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507 }
3508
Mingming Yin21854652016-04-13 11:54:02 -07003509 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d out->flags:%x, flags:%x",
3510 __func__, devices, flags, format, out->sample_rate, out->bit_width, out->flags, flags);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003511 /* TODO remove this hardcoding and check why width is zero*/
3512 if (out->bit_width == 0)
3513 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003514 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3515 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003516 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303517 out->bit_width, out->channel_mask,
3518 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003519 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3520 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3521 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003522 if(adev->primary_output == NULL)
3523 adev->primary_output = out;
3524 else {
3525 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003526 ret = -EEXIST;
3527 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003528 }
3529 }
3530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 /* Check if this usecase is already existing */
3532 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003533 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3534 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003537 ret = -EEXIST;
3538 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539 }
3540 pthread_mutex_unlock(&adev->lock);
3541
3542 out->stream.common.get_sample_rate = out_get_sample_rate;
3543 out->stream.common.set_sample_rate = out_set_sample_rate;
3544 out->stream.common.get_buffer_size = out_get_buffer_size;
3545 out->stream.common.get_channels = out_get_channels;
3546 out->stream.common.get_format = out_get_format;
3547 out->stream.common.set_format = out_set_format;
3548 out->stream.common.standby = out_standby;
3549 out->stream.common.dump = out_dump;
3550 out->stream.common.set_parameters = out_set_parameters;
3551 out->stream.common.get_parameters = out_get_parameters;
3552 out->stream.common.add_audio_effect = out_add_audio_effect;
3553 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3554 out->stream.get_latency = out_get_latency;
3555 out->stream.set_volume = out_set_volume;
3556 out->stream.write = out_write;
3557 out->stream.get_render_position = out_get_render_position;
3558 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003559 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003562 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003563 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564
3565 config->format = out->stream.common.get_format(&out->stream.common);
3566 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3567 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3568
3569 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303570 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003571 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003572
3573 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3574 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3575 popcount(out->channel_mask), out->playback_started);
3576
Eric Laurent994a6932013-07-17 11:51:42 -07003577 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003579
3580error_open:
3581 free(out);
3582 *stream_out = NULL;
3583 ALOGD("%s: exit: ret %d", __func__, ret);
3584 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003585}
3586
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003587static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003588 struct audio_stream_out *stream)
3589{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003590 struct stream_out *out = (struct stream_out *)stream;
3591 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003592 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003593
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303594 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3595
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003596 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303597 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003598 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303599 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003600 if(ret != 0)
3601 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3602 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003603 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003604 out_standby(&stream->common);
3605
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003606 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003607 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003608 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003609 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003610 if (out->compr_config.codec != NULL)
3611 free(out->compr_config.codec);
3612 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003613
3614 if (adev->voice_tx_output == out)
3615 adev->voice_tx_output = NULL;
3616
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003617 pthread_cond_destroy(&out->cond);
3618 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003620 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003621}
3622
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003623static void close_compress_sessions(struct audio_device *adev)
3624{
Mingming Yin7b762e72015-03-04 13:47:32 -08003625 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303626 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003627 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003628 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303629
3630 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003631 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303632 if (is_offload_usecase(usecase->id)) {
3633 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003634 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3635 out = usecase->stream.out;
3636 pthread_mutex_unlock(&adev->lock);
3637 out_standby(&out->stream.common);
3638 pthread_mutex_lock(&adev->lock);
3639 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303640 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003641 }
3642 pthread_mutex_unlock(&adev->lock);
3643}
3644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3646{
3647 struct audio_device *adev = (struct audio_device *)dev;
3648 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003650 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003651 int ret;
3652 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003653
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003654 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303657 if (!parms)
3658 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003659 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3660 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303661 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303662 if (strstr(snd_card_status, "OFFLINE")) {
3663 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303664 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003665 //close compress sessions on OFFLINE status
3666 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303667 } else if (strstr(snd_card_status, "ONLINE")) {
3668 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303669 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003670 //send dts hpx license if enabled
3671 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303672 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303673 }
3674
3675 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003676 status = voice_set_parameters(adev, parms);
3677 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003678 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003680 status = platform_set_parameters(adev->platform, parms);
3681 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003682 goto done;
3683
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003684 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3685 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003686 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3688 adev->bluetooth_nrec = true;
3689 else
3690 adev->bluetooth_nrec = false;
3691 }
3692
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003693 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3694 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003695 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3696 adev->screen_off = false;
3697 else
3698 adev->screen_off = true;
3699 }
3700
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003701 ret = str_parms_get_int(parms, "rotation", &val);
3702 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003703 bool reverse_speakers = false;
3704 switch(val) {
3705 // FIXME: note that the code below assumes that the speakers are in the correct placement
3706 // relative to the user when the device is rotated 90deg from its default rotation. This
3707 // assumption is device-specific, not platform-specific like this code.
3708 case 270:
3709 reverse_speakers = true;
3710 break;
3711 case 0:
3712 case 90:
3713 case 180:
3714 break;
3715 default:
3716 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003717 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003718 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003719 if (status == 0) {
3720 if (adev->speaker_lr_swap != reverse_speakers) {
3721 adev->speaker_lr_swap = reverse_speakers;
3722 // only update the selected device if there is active pcm playback
3723 struct audio_usecase *usecase;
3724 struct listnode *node;
3725 list_for_each(node, &adev->usecase_list) {
3726 usecase = node_to_item(node, struct audio_usecase, list);
3727 if (usecase->type == PCM_PLAYBACK) {
3728 select_devices(adev, usecase->id);
3729 break;
3730 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003731 }
3732 }
3733 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003734 }
3735
Mingming Yin514a8bc2014-07-29 15:22:21 -07003736 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3737 if (ret >= 0) {
3738 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3739 adev->bt_wb_speech_enabled = true;
3740 else
3741 adev->bt_wb_speech_enabled = false;
3742 }
3743
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003744 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3745 if (ret >= 0) {
3746 val = atoi(value);
3747 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3748 ALOGV("cache new edid");
3749 platform_cache_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003750 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3751 /*
3752 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
3753 * Per AudioPolicyManager, USB device is higher priority than WFD.
3754 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
3755 * If WFD use case occupies AFE proxy, it may result unintended behavior while
3756 * starting voice call on USB
3757 */
3758 ALOGV("detected USB connect .. disable proxy");
3759 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003760 }
3761 }
3762
3763 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3764 if (ret >= 0) {
3765 val = atoi(value);
3766 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3767 ALOGV("invalidate cached edid");
3768 platform_invalidate_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003769 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3770 ALOGV("detected USB disconnect .. enable proxy");
3771 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003772 }
3773 }
3774
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003775 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003776
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003777done:
3778 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003779 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303780error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003781 ALOGV("%s: exit with code(%d)", __func__, status);
3782 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783}
3784
3785static char* adev_get_parameters(const struct audio_hw_device *dev,
3786 const char *keys)
3787{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003788 struct audio_device *adev = (struct audio_device *)dev;
3789 struct str_parms *reply = str_parms_create();
3790 struct str_parms *query = str_parms_create_str(keys);
3791 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303792 char value[256] = {0};
3793 int ret = 0;
3794
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003795 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003796 if (reply) {
3797 str_parms_destroy(reply);
3798 }
3799 if (query) {
3800 str_parms_destroy(query);
3801 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003802 ALOGE("adev_get_parameters: failed to create query or reply");
3803 return NULL;
3804 }
3805
Naresh Tannirud7205b62014-06-20 02:54:48 +05303806 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3807 sizeof(value));
3808 if (ret >=0) {
3809 int val = 1;
3810 pthread_mutex_lock(&adev->snd_card_status.lock);
3811 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3812 val = 0;
3813 pthread_mutex_unlock(&adev->snd_card_status.lock);
3814 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3815 goto exit;
3816 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003817
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003818 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003819 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003820 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003821 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303822 pthread_mutex_unlock(&adev->lock);
3823
Naresh Tannirud7205b62014-06-20 02:54:48 +05303824exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003825 str = str_parms_to_str(reply);
3826 str_parms_destroy(query);
3827 str_parms_destroy(reply);
3828
3829 ALOGV("%s: exit: returns - %s", __func__, str);
3830 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003831}
3832
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003833static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003834{
3835 return 0;
3836}
3837
3838static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3839{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003840 int ret;
3841 struct audio_device *adev = (struct audio_device *)dev;
3842 pthread_mutex_lock(&adev->lock);
3843 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003844 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003845 pthread_mutex_unlock(&adev->lock);
3846 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003847}
3848
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003849static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3850 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003851{
3852 return -ENOSYS;
3853}
3854
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003855static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3856 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003857{
3858 return -ENOSYS;
3859}
3860
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003861static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3862 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003863{
3864 return -ENOSYS;
3865}
3866
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003867static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3868 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003869{
3870 return -ENOSYS;
3871}
3872
3873static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3874{
3875 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003876
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003877 pthread_mutex_lock(&adev->lock);
3878 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003879 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003880 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003881 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003882 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003883 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003884 adev->current_call_output = NULL;
3885 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886 }
3887 pthread_mutex_unlock(&adev->lock);
3888 return 0;
3889}
3890
3891static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3892{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003893 int ret;
3894
3895 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003896 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003897 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3898 pthread_mutex_unlock(&adev->lock);
3899
3900 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901}
3902
3903static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3904{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003905 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003906 return 0;
3907}
3908
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003909static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003910 const struct audio_config *config)
3911{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003912 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003914 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3915 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003916}
3917
3918static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003919 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003920 audio_devices_t devices,
3921 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003922 struct audio_stream_in **stream_in,
3923 audio_input_flags_t flags __unused,
3924 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003925 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003926{
3927 struct audio_device *adev = (struct audio_device *)dev;
3928 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003929 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003930 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003931 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003933 *stream_in = NULL;
3934 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3935 return -EINVAL;
3936
3937 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003938
3939 if (!in) {
3940 ALOGE("failed to allocate input stream");
3941 return -ENOMEM;
3942 }
3943
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303944 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303945 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
3946 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003947 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003948 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003949
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003950 in->stream.common.get_sample_rate = in_get_sample_rate;
3951 in->stream.common.set_sample_rate = in_set_sample_rate;
3952 in->stream.common.get_buffer_size = in_get_buffer_size;
3953 in->stream.common.get_channels = in_get_channels;
3954 in->stream.common.get_format = in_get_format;
3955 in->stream.common.set_format = in_set_format;
3956 in->stream.common.standby = in_standby;
3957 in->stream.common.dump = in_dump;
3958 in->stream.common.set_parameters = in_set_parameters;
3959 in->stream.common.get_parameters = in_get_parameters;
3960 in->stream.common.add_audio_effect = in_add_audio_effect;
3961 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3962 in->stream.set_gain = in_set_gain;
3963 in->stream.read = in_read;
3964 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3965
3966 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003967 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003968 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003969 in->standby = 1;
3970 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003971 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003972 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003973
3974 /* Update config params with the requested sample rate and channels */
3975 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003976 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3977 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3978 is_low_latency = true;
3979#if LOW_LATENCY_CAPTURE_USE_CASE
3980 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3981#endif
3982 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003983 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003984 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003985 in->format = config->format;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303986 in->bit_width = 16;
3987 in->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003988
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003989 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303990 if (adev->mode != AUDIO_MODE_IN_CALL) {
3991 ret = -EINVAL;
3992 goto err_open;
3993 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003994 if (config->sample_rate == 0)
3995 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3996 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3997 config->sample_rate != 8000) {
3998 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3999 ret = -EINVAL;
4000 goto err_open;
4001 }
4002 if (config->format == AUDIO_FORMAT_DEFAULT)
4003 config->format = AUDIO_FORMAT_PCM_16_BIT;
4004 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4005 config->format = AUDIO_FORMAT_PCM_16_BIT;
4006 ret = -EINVAL;
4007 goto err_open;
4008 }
4009
4010 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4011 in->config = pcm_config_afe_proxy_record;
4012 in->config.channels = channel_count;
4013 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304014 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304015 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4016 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004017 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004018 audio_extn_compr_cap_format_supported(config->format) &&
4019 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004020 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004021 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304022 /* restrict 24 bit capture for unprocessed source only
4023 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4024 */
4025 if (config->format == AUDIO_FORMAT_DEFAULT) {
4026 config->format = AUDIO_FORMAT_PCM_16_BIT;
4027 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4028 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4029 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4030 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4031 bool ret_error = false;
4032 in->bit_width = 24;
4033 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4034 from HAL is 24_packed and 8_24
4035 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4036 24_packed return error indicating supported format is 24_packed
4037 *> In case of any other source requesting 24 bit or float return error
4038 indicating format supported is 16 bit only.
4039
4040 on error flinger will retry with supported format passed
4041 */
4042 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4043 (source != AUDIO_SOURCE_CAMCORDER)) {
4044 config->format = AUDIO_FORMAT_PCM_16_BIT;
4045 if( config->sample_rate > 48000)
4046 config->sample_rate = 48000;
4047 ret_error = true;
4048 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4049 in->config.format = PCM_FORMAT_S24_3LE;
4050 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4051 in->config.format = PCM_FORMAT_S24_LE;
4052 } else {
4053 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4054 ret_error = true;
4055 }
4056
4057 if (ret_error) {
4058 ret = -EINVAL;
4059 goto err_open;
4060 }
4061 }
4062
4063 in->format = config->format;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004064 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004065 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004066 buffer_size = get_input_buffer_size(config->sample_rate,
4067 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004068 channel_count,
4069 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004070 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004071 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4072 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4073 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004074 (in->config.rate == 8000 || in->config.rate == 16000 ||
4075 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004076 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4077 voice_extn_compress_voip_open_input_stream(in);
4078 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004079 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004080
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004081 /* This stream could be for sound trigger lab,
4082 get sound trigger pcm if present */
4083 audio_extn_sound_trigger_check_and_get_session(in);
4084
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004086 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004087 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004088
4089err_open:
4090 free(in);
4091 *stream_in = NULL;
4092 return ret;
4093}
4094
4095static void adev_close_input_stream(struct audio_hw_device *dev,
4096 struct audio_stream_in *stream)
4097{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004098 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004099 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004100 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304101
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304102 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004103
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304104 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004105 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304106
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004107 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304108 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004109 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304110 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004111 if (ret != 0)
4112 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4113 __func__, ret);
4114 } else
4115 in_standby(&stream->common);
4116
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004117 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004118 audio_extn_ssr_deinit();
4119 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004120
Mingming Yine62d7842013-10-25 16:26:03 -07004121 if(audio_extn_compr_cap_enabled() &&
4122 audio_extn_compr_cap_format_supported(in->config.format))
4123 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004124
Mingming Yinfd7607b2016-01-22 12:48:44 -08004125 if (in->is_st_session) {
4126 ALOGV("%s: sound trigger pcm stop lab", __func__);
4127 audio_extn_sound_trigger_stop_lab(in);
4128 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004129 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130 return;
4131}
4132
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004133static int adev_dump(const audio_hw_device_t *device __unused,
4134 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004135{
4136 return 0;
4137}
4138
4139static int adev_close(hw_device_t *device)
4140{
4141 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004142
4143 if (!adev)
4144 return 0;
4145
4146 pthread_mutex_lock(&adev_init_lock);
4147
4148 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004149 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004150 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004151 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004152 audio_route_free(adev->audio_route);
4153 free(adev->snd_dev_ref_cnt);
4154 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004155 if (adev->adm_deinit)
4156 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004157 free(device);
4158 adev = NULL;
4159 }
4160 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004161
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162 return 0;
4163}
4164
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004165/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4166 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4167 * just that it _might_ work.
4168 */
4169static int period_size_is_plausible_for_low_latency(int period_size)
4170{
4171 switch (period_size) {
4172 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004173 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004174 case 240:
4175 case 320:
4176 case 480:
4177 return 1;
4178 default:
4179 return 0;
4180 }
4181}
4182
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004183static int adev_open(const hw_module_t *module, const char *name,
4184 hw_device_t **device)
4185{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004186 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004187 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4188
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004189 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004190 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004191 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004192 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004193 ALOGD("%s: returning existing instance of adev", __func__);
4194 ALOGD("%s: exit", __func__);
4195 pthread_mutex_unlock(&adev_init_lock);
4196 return 0;
4197 }
4198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004199 adev = calloc(1, sizeof(struct audio_device));
4200
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004201 if (!adev) {
4202 pthread_mutex_unlock(&adev_init_lock);
4203 return -ENOMEM;
4204 }
4205
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004206 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004208 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4209 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4210 adev->device.common.module = (struct hw_module_t *)module;
4211 adev->device.common.close = adev_close;
4212
4213 adev->device.init_check = adev_init_check;
4214 adev->device.set_voice_volume = adev_set_voice_volume;
4215 adev->device.set_master_volume = adev_set_master_volume;
4216 adev->device.get_master_volume = adev_get_master_volume;
4217 adev->device.set_master_mute = adev_set_master_mute;
4218 adev->device.get_master_mute = adev_get_master_mute;
4219 adev->device.set_mode = adev_set_mode;
4220 adev->device.set_mic_mute = adev_set_mic_mute;
4221 adev->device.get_mic_mute = adev_get_mic_mute;
4222 adev->device.set_parameters = adev_set_parameters;
4223 adev->device.get_parameters = adev_get_parameters;
4224 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4225 adev->device.open_output_stream = adev_open_output_stream;
4226 adev->device.close_output_stream = adev_close_output_stream;
4227 adev->device.open_input_stream = adev_open_input_stream;
4228 adev->device.close_input_stream = adev_close_input_stream;
4229 adev->device.dump = adev_dump;
4230
4231 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004232 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004233 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004234 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004235 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004236 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004237 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004238 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004239 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004240 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004241 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004242 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004243 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004244 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304245 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304246 adev->perf_lock_opts[0] = 0x101;
4247 adev->perf_lock_opts[1] = 0x20E;
4248 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304249
4250 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4251 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004252 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004253 adev->platform = platform_init(adev);
4254 if (!adev->platform) {
4255 free(adev->snd_dev_ref_cnt);
4256 free(adev);
4257 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4258 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004259 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004260 return -EINVAL;
4261 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004262
Naresh Tanniru4c630392014-05-12 01:05:52 +05304263 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4264
Eric Laurentc4aef752013-09-12 17:45:53 -07004265 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4266 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4267 if (adev->visualizer_lib == NULL) {
4268 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4269 } else {
4270 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4271 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004272 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004273 "visualizer_hal_start_output");
4274 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004275 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004276 "visualizer_hal_stop_output");
4277 }
4278 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004279 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004280 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004281
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004282 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4283 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4284 if (adev->offload_effects_lib == NULL) {
4285 ALOGE("%s: DLOPEN failed for %s", __func__,
4286 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4287 } else {
4288 ALOGV("%s: DLOPEN successful for %s", __func__,
4289 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4290 adev->offload_effects_start_output =
4291 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4292 "offload_effects_bundle_hal_start_output");
4293 adev->offload_effects_stop_output =
4294 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4295 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004296 adev->offload_effects_set_hpx_state =
4297 (int (*)(bool))dlsym(adev->offload_effects_lib,
4298 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304299 adev->offload_effects_get_parameters =
4300 (void (*)(struct str_parms *, struct str_parms *))
4301 dlsym(adev->offload_effects_lib,
4302 "offload_effects_bundle_get_parameters");
4303 adev->offload_effects_set_parameters =
4304 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4305 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004306 }
4307 }
4308
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004309 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4310 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4311 if (adev->adm_lib == NULL) {
4312 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4313 } else {
4314 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4315 adev->adm_init = (adm_init_t)
4316 dlsym(adev->adm_lib, "adm_init");
4317 adev->adm_deinit = (adm_deinit_t)
4318 dlsym(adev->adm_lib, "adm_deinit");
4319 adev->adm_register_input_stream = (adm_register_input_stream_t)
4320 dlsym(adev->adm_lib, "adm_register_input_stream");
4321 adev->adm_register_output_stream = (adm_register_output_stream_t)
4322 dlsym(adev->adm_lib, "adm_register_output_stream");
4323 adev->adm_deregister_stream = (adm_deregister_stream_t)
4324 dlsym(adev->adm_lib, "adm_deregister_stream");
4325 adev->adm_request_focus = (adm_request_focus_t)
4326 dlsym(adev->adm_lib, "adm_request_focus");
4327 adev->adm_abandon_focus = (adm_abandon_focus_t)
4328 dlsym(adev->adm_lib, "adm_abandon_focus");
4329 }
4330 }
4331
Mingming Yin514a8bc2014-07-29 15:22:21 -07004332 adev->bt_wb_speech_enabled = false;
4333
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004334 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004335 *device = &adev->device.common;
4336
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004337 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4338 &adev->streams_output_cfg_list);
4339
Kiran Kandi910e1862013-10-29 13:29:42 -07004340 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004341
4342 char value[PROPERTY_VALUE_MAX];
4343 int trial;
4344 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4345 trial = atoi(value);
4346 if (period_size_is_plausible_for_low_latency(trial)) {
4347 pcm_config_low_latency.period_size = trial;
4348 pcm_config_low_latency.start_threshold = trial / 4;
4349 pcm_config_low_latency.avail_min = trial / 4;
4350 configured_low_latency_capture_period_size = trial;
4351 }
4352 }
4353 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4354 trial = atoi(value);
4355 if (period_size_is_plausible_for_low_latency(trial)) {
4356 configured_low_latency_capture_period_size = trial;
4357 }
4358 }
4359
vivek mehta446c3962015-09-14 10:57:35 -07004360 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004361 pthread_mutex_unlock(&adev_init_lock);
4362
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004363 if (adev->adm_init)
4364 adev->adm_data = adev->adm_init();
4365
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304366 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004367 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004368 return 0;
4369}
4370
4371static struct hw_module_methods_t hal_module_methods = {
4372 .open = adev_open,
4373};
4374
4375struct audio_module HAL_MODULE_INFO_SYM = {
4376 .common = {
4377 .tag = HARDWARE_MODULE_TAG,
4378 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4379 .hal_api_version = HARDWARE_HAL_API_VERSION,
4380 .id = AUDIO_HARDWARE_MODULE_ID,
4381 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004382 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004383 .methods = &hal_module_methods,
4384 },
4385};