blob: aa1bc053b3faabc261d7e0a867094069e054e3a1 [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
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700754static void check_and_route_capture_usecases(struct audio_device *adev,
755 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
763 /*
764 * This function is to make sure that all the active capture usecases
765 * are always routed to the same input sound device.
766 * For example, if audio-record and voice-call usecases are currently
767 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
768 * is received for voice call then we have to make sure that audio-record
769 * usecase is also switched to earpiece i.e. voice-dmic-ef,
770 * because of the limitation that two devices cannot be enabled
771 * at the same time if they share the same backend.
772 */
773 for (i = 0; i < AUDIO_USECASE_MAX; i++)
774 switch_device[i] = false;
775
776 list_for_each(node, &adev->usecase_list) {
777 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800778 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700779 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700780 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700781 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530782 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
783 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700784 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700785 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
786 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700787 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700788 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700789 switch_device[usecase->id] = true;
790 num_uc_to_switch++;
791 }
792 }
793
794 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700795 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700796
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530797 /* Make sure the previous devices to be disabled first and then enable the
798 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700799 list_for_each(node, &adev->usecase_list) {
800 usecase = node_to_item(node, struct audio_usecase, list);
801 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700802 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800803 }
804 }
805
806 list_for_each(node, &adev->usecase_list) {
807 usecase = node_to_item(node, struct audio_usecase, list);
808 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700809 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700810 }
811 }
812
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700813 /* Re-route all the usecases on the shared backend other than the
814 specified usecase to new snd devices */
815 list_for_each(node, &adev->usecase_list) {
816 usecase = node_to_item(node, struct audio_usecase, list);
817 /* Update the in_snd_device only before enabling the audio route */
818 if (switch_device[usecase->id] ) {
819 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800820 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530821 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700822 }
823 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700824 }
825}
826
Mingming Yin3a941d42016-02-17 18:08:05 -0800827static void reset_hdmi_sink_caps(struct stream_out *out) {
828 int i = 0;
829
830 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
831 out->supported_channel_masks[i] = 0;
832 }
833 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
834 out->supported_formats[i] = 0;
835 }
836 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
837 out->supported_sample_rates[i] = 0;
838 }
839}
840
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800841/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -0800842static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800843{
Mingming Yin3a941d42016-02-17 18:08:05 -0800844 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700845 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800846
Mingming Yin3a941d42016-02-17 18:08:05 -0800847 reset_hdmi_sink_caps(out);
848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800849 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800850 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -0800851 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700852 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -0800853 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
854 case 6:
855 ALOGV("%s: HDMI supports 5.1 channels", __func__);
856 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
857 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
858 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
859 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
860 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
861 case 2:
862 ALOGV("%s: HDMI supports 2 channels", __func__);
863 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_STEREO;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800864 break;
865 default:
Mingming Yin3a941d42016-02-17 18:08:05 -0800866 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700867 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800868 break;
869 }
Mingming Yin3a941d42016-02-17 18:08:05 -0800870
871 // check channel format caps
872 i = 0;
873 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
874 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
875 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
876 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
877 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
878 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
879 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
880 }
881
882 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
883 ALOGV(":%s HDMI supports DTS format", __func__);
884 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
885 }
886
887 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
888 ALOGV(":%s HDMI supports DTS HD format", __func__);
889 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
890 }
891
892
893 // check sample rate caps
894 i = 0;
895 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
896 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
897 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
898 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
899 }
900 }
901
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700902 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800903}
904
Alexy Josephb1379942016-01-29 15:49:38 -0800905audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800906 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700907{
908 struct audio_usecase *usecase;
909 struct listnode *node;
910
911 list_for_each(node, &adev->usecase_list) {
912 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800913 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700914 ALOGV("%s: usecase id %d", __func__, usecase->id);
915 return usecase->id;
916 }
917 }
918 return USECASE_INVALID;
919}
920
Alexy Josephb1379942016-01-29 15:49:38 -0800921struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700922 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700923{
924 struct audio_usecase *usecase;
925 struct listnode *node;
926
927 list_for_each(node, &adev->usecase_list) {
928 usecase = node_to_item(node, struct audio_usecase, list);
929 if (usecase->id == uc_id)
930 return usecase;
931 }
932 return NULL;
933}
934
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530935/*
936 * is a true native playback active
937 */
938bool audio_is_true_native_stream_active(struct audio_device *adev)
939{
940 bool active = false;
941 int i = 0;
942 struct listnode *node;
943
944 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
945 ALOGV("%s:napb: not in true mode or non hdphones device",
946 __func__);
947 active = false;
948 goto exit;
949 }
950
951 list_for_each(node, &adev->usecase_list) {
952 struct audio_usecase *uc;
953 uc = node_to_item(node, struct audio_usecase, list);
954 struct stream_out *curr_out =
955 (struct stream_out*) uc->stream.out;
956
957 if (curr_out && PCM_PLAYBACK == uc->type) {
958 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
959 "(%d) device %s", __func__, i++, use_case_table[uc->id],
960 uc->id, curr_out->sample_rate,
961 curr_out->bit_width,
962 platform_get_snd_device_name(uc->out_snd_device));
963
964 if (is_offload_usecase(uc->id) &&
965 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
966 active = true;
967 ALOGD("%s:napb:native stream detected", __func__);
968 }
969 }
970 }
971exit:
972 return active;
973}
974
975
976static bool force_device_switch(struct audio_usecase *usecase)
977{
978 bool ret = false;
979 bool is_it_true_mode = false;
980
981 if (is_offload_usecase(usecase->id) &&
982 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +0800983 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
984 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
985 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530986 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
987 if ((is_it_true_mode && !adev->native_playback_enabled) ||
988 (!is_it_true_mode && adev->native_playback_enabled)){
989 ret = true;
990 ALOGD("napb: time to toggle native mode");
991 }
992 }
993
994 return ret;
995}
996
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700997int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800998{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800999 snd_device_t out_snd_device = SND_DEVICE_NONE;
1000 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001001 struct audio_usecase *usecase = NULL;
1002 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001003 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001004 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001005 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001006 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001007
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301008 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1009
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001010 usecase = get_usecase_from_list(adev, uc_id);
1011 if (usecase == NULL) {
1012 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1013 return -EINVAL;
1014 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001015
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001016 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001017 (usecase->type == VOIP_CALL) ||
1018 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001019 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001020 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001021 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001022 usecase->devices = usecase->stream.out->devices;
1023 } else {
1024 /*
1025 * If the voice call is active, use the sound devices of voice call usecase
1026 * so that it would not result any device switch. All the usecases will
1027 * be switched to new device when select_devices() is called for voice call
1028 * usecase. This is to avoid switching devices for voice call when
1029 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001030 * choose voice call device only if the use case device is
1031 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001032 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001033 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001034 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001035 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001036 if (((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1037 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND))) ||
1038 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001039 in_snd_device = vc_usecase->in_snd_device;
1040 out_snd_device = vc_usecase->out_snd_device;
1041 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001042 } else if (voice_extn_compress_voip_is_active(adev)) {
1043 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001044 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +05301045 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001046 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001047 in_snd_device = voip_usecase->in_snd_device;
1048 out_snd_device = voip_usecase->out_snd_device;
1049 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001050 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001051 hfp_ucid = audio_extn_hfp_get_usecase();
1052 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001053 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001054 in_snd_device = hfp_usecase->in_snd_device;
1055 out_snd_device = hfp_usecase->out_snd_device;
1056 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001057 }
1058 if (usecase->type == PCM_PLAYBACK) {
1059 usecase->devices = usecase->stream.out->devices;
1060 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001061 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001062 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001063 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001064 if (usecase->stream.out == adev->primary_output &&
1065 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001066 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001067 select_devices(adev, adev->active_input->usecase);
1068 }
1069 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001070 } else if (usecase->type == PCM_CAPTURE) {
1071 usecase->devices = usecase->stream.in->device;
1072 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001073 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001074 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001075 if (adev->active_input &&
1076 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301077 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1078 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1079 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001080 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001081 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001082 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1083 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001084 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001085 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001086 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001087 }
1088 }
1089
1090 if (out_snd_device == usecase->out_snd_device &&
1091 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301092
1093 if (!force_device_switch(usecase))
1094 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001095 }
1096
sangwoobc677242013-08-08 16:53:43 +09001097 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001098 out_snd_device, platform_get_snd_device_name(out_snd_device),
1099 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001101 /*
1102 * Limitation: While in call, to do a device switch we need to disable
1103 * and enable both RX and TX devices though one of them is same as current
1104 * device.
1105 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001106 if ((usecase->type == VOICE_CALL) &&
1107 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1108 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001109 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001110 }
1111
1112 if (((usecase->type == VOICE_CALL) ||
1113 (usecase->type == VOIP_CALL)) &&
1114 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1115 /* Disable sidetone only if voice/voip call already exists */
1116 if (voice_is_call_state_active(adev) ||
1117 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001118 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001119 }
1120
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001121 /* Disable current sound devices */
1122 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001123 disable_audio_route(adev, usecase);
1124 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001125 }
1126
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001127 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001128 disable_audio_route(adev, usecase);
1129 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001130 }
1131
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001132 /* Applicable only on the targets that has external modem.
1133 * New device information should be sent to modem before enabling
1134 * the devices to reduce in-call device switch time.
1135 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001136 if ((usecase->type == VOICE_CALL) &&
1137 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1138 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001139 status = platform_switch_voice_call_enable_device_config(adev->platform,
1140 out_snd_device,
1141 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001142 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001143
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001144 /* Enable new sound devices */
1145 if (out_snd_device != SND_DEVICE_NONE) {
1146 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
1147 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001148 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001149 }
1150
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001151 if (in_snd_device != SND_DEVICE_NONE) {
1152 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001153 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001154 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001155
Avinash Vaish71a8b972014-07-24 15:36:33 +05301156 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001157 status = platform_switch_voice_call_device_post(adev->platform,
1158 out_snd_device,
1159 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301160 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001161 /* Enable sidetone only if voice/voip call already exists */
1162 if (voice_is_call_state_active(adev) ||
1163 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001164 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301165 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001166
sangwoo170731f2013-06-08 15:36:36 +09001167 usecase->in_snd_device = in_snd_device;
1168 usecase->out_snd_device = out_snd_device;
1169
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301170 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001171 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301172 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001173 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301174 usecase->stream.out->flags,
1175 usecase->stream.out->format,
1176 usecase->stream.out->sample_rate,
1177 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301178 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301179 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001180 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301181 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001182
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001183 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001184
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001185 /* Applicable only on the targets that has external modem.
1186 * Enable device command should be sent to modem only after
1187 * enabling voice call mixer controls
1188 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001189 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001190 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1191 out_snd_device,
1192 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301193 ALOGD("%s: done",__func__);
1194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001195 return status;
1196}
1197
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001198static int stop_input_stream(struct stream_in *in)
1199{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301200 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001201 struct audio_usecase *uc_info;
1202 struct audio_device *adev = in->dev;
1203
Eric Laurentc8400632013-02-14 19:04:54 -08001204 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001205
Eric Laurent994a6932013-07-17 11:51:42 -07001206 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001207 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001208 uc_info = get_usecase_from_list(adev, in->usecase);
1209 if (uc_info == NULL) {
1210 ALOGE("%s: Could not find the usecase (%d) in the list",
1211 __func__, in->usecase);
1212 return -EINVAL;
1213 }
1214
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001215 /* Close in-call recording streams */
1216 voice_check_and_stop_incall_rec_usecase(adev, in);
1217
Eric Laurent150dbfe2013-02-27 14:31:02 -08001218 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001219 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001220
1221 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001222 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001223
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001224 list_remove(&uc_info->list);
1225 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001226
Eric Laurent994a6932013-07-17 11:51:42 -07001227 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001228 return ret;
1229}
1230
1231int start_input_stream(struct stream_in *in)
1232{
1233 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001234 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001235 struct audio_usecase *uc_info;
1236 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301237 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001238
Mingming Yin2664a5b2015-09-03 10:53:11 -07001239 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1240 if (get_usecase_from_list(adev, usecase) == NULL)
1241 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301242 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1243 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001244
Naresh Tanniru80659832014-06-04 18:17:56 +05301245
1246 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301247 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301248 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301249 goto error_config;
1250 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301251
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001252 /* Check if source matches incall recording usecase criteria */
1253 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1254 if (ret)
1255 goto error_config;
1256 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001257 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1258
1259 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1260 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1261 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1262 goto error_config;
1263 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001264
Eric Laurentb23d5282013-05-14 15:27:20 -07001265 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001266 if (in->pcm_device_id < 0) {
1267 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1268 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001269 ret = -EINVAL;
1270 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001271 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001272
1273 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001274 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001275
1276 if (!uc_info) {
1277 ret = -ENOMEM;
1278 goto error_config;
1279 }
1280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001281 uc_info->id = in->usecase;
1282 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001283 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001284 uc_info->devices = in->device;
1285 uc_info->in_snd_device = SND_DEVICE_NONE;
1286 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001287
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001288 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301289 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1290 adev->perf_lock_opts,
1291 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001292 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001293
Eric Laurentc8400632013-02-14 19:04:54 -08001294 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001295 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1296
1297 unsigned int flags = PCM_IN;
1298 unsigned int pcm_open_retry_count = 0;
1299
1300 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1301 flags |= PCM_MMAP | PCM_NOIRQ;
1302 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1303 }
1304
1305 while (1) {
1306 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1307 flags, &in->config);
1308 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1309 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1310 if (in->pcm != NULL) {
1311 pcm_close(in->pcm);
1312 in->pcm = NULL;
1313 }
1314 if (pcm_open_retry_count-- == 0) {
1315 ret = -EIO;
1316 goto error_open;
1317 }
1318 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1319 continue;
1320 }
1321 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001322 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001323
1324 ALOGV("%s: pcm_prepare", __func__);
1325 ret = pcm_prepare(in->pcm);
1326 if (ret < 0) {
1327 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1328 pcm_close(in->pcm);
1329 in->pcm = NULL;
1330 goto error_open;
1331 }
1332
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301333 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001334 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001335
Eric Laurentc8400632013-02-14 19:04:54 -08001336 return ret;
1337
1338error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301339 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001340 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001341error_config:
1342 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301343 /*
1344 * sleep 50ms to allow sufficient time for kernel
1345 * drivers to recover incases like SSR.
1346 */
1347 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001348 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001349
1350 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001351}
1352
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001353void lock_input_stream(struct stream_in *in)
1354{
1355 pthread_mutex_lock(&in->pre_lock);
1356 pthread_mutex_lock(&in->lock);
1357 pthread_mutex_unlock(&in->pre_lock);
1358}
1359
1360void lock_output_stream(struct stream_out *out)
1361{
1362 pthread_mutex_lock(&out->pre_lock);
1363 pthread_mutex_lock(&out->lock);
1364 pthread_mutex_unlock(&out->pre_lock);
1365}
1366
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001367/* must be called with out->lock locked */
1368static int send_offload_cmd_l(struct stream_out* out, int command)
1369{
1370 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1371
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001372 if (!cmd) {
1373 ALOGE("failed to allocate mem for command 0x%x", command);
1374 return -ENOMEM;
1375 }
1376
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001377 ALOGVV("%s %d", __func__, command);
1378
1379 cmd->cmd = command;
1380 list_add_tail(&out->offload_cmd_list, &cmd->node);
1381 pthread_cond_signal(&out->offload_cond);
1382 return 0;
1383}
1384
1385/* must be called iwth out->lock locked */
1386static void stop_compressed_output_l(struct stream_out *out)
1387{
1388 out->offload_state = OFFLOAD_STATE_IDLE;
1389 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001390 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001391 if (out->compr != NULL) {
1392 compress_stop(out->compr);
1393 while (out->offload_thread_blocked) {
1394 pthread_cond_wait(&out->cond, &out->lock);
1395 }
1396 }
1397}
1398
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001399bool is_offload_usecase(audio_usecase_t uc_id)
1400{
1401 unsigned int i;
1402 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1403 if (uc_id == offload_usecases[i])
1404 return true;
1405 }
1406 return false;
1407}
1408
vivek mehta446c3962015-09-14 10:57:35 -07001409static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001410{
vivek mehta446c3962015-09-14 10:57:35 -07001411 audio_usecase_t ret_uc = USECASE_INVALID;
1412 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001413 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001414 if (!adev->multi_offload_enable) {
1415 if (is_direct_pcm)
1416 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1417 else
1418 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001419
vivek mehta446c3962015-09-14 10:57:35 -07001420 pthread_mutex_lock(&adev->lock);
1421 if (get_usecase_from_list(adev, ret_uc) != NULL)
1422 ret_uc = USECASE_INVALID;
1423 pthread_mutex_unlock(&adev->lock);
1424
1425 return ret_uc;
1426 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001427
1428 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001429 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1430 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1431 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1432 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001433 break;
1434 }
1435 }
vivek mehta446c3962015-09-14 10:57:35 -07001436
1437 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1438 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001439}
1440
1441static void free_offload_usecase(struct audio_device *adev,
1442 audio_usecase_t uc_id)
1443{
vivek mehta446c3962015-09-14 10:57:35 -07001444 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001445 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001446
1447 if (!adev->multi_offload_enable)
1448 return;
1449
1450 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1451 if (offload_usecases[offload_uc_index] == uc_id) {
1452 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001453 break;
1454 }
1455 }
1456 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1457}
1458
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001459static void *offload_thread_loop(void *context)
1460{
1461 struct stream_out *out = (struct stream_out *) context;
1462 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001463 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001464
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001465 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1466 set_sched_policy(0, SP_FOREGROUND);
1467 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1468
1469 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001470 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001471 for (;;) {
1472 struct offload_cmd *cmd = NULL;
1473 stream_callback_event_t event;
1474 bool send_callback = false;
1475
1476 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1477 __func__, list_empty(&out->offload_cmd_list),
1478 out->offload_state);
1479 if (list_empty(&out->offload_cmd_list)) {
1480 ALOGV("%s SLEEPING", __func__);
1481 pthread_cond_wait(&out->offload_cond, &out->lock);
1482 ALOGV("%s RUNNING", __func__);
1483 continue;
1484 }
1485
1486 item = list_head(&out->offload_cmd_list);
1487 cmd = node_to_item(item, struct offload_cmd, node);
1488 list_remove(item);
1489
1490 ALOGVV("%s STATE %d CMD %d out->compr %p",
1491 __func__, out->offload_state, cmd->cmd, out->compr);
1492
1493 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1494 free(cmd);
1495 break;
1496 }
1497
1498 if (out->compr == NULL) {
1499 ALOGE("%s: Compress handle is NULL", __func__);
1500 pthread_cond_signal(&out->cond);
1501 continue;
1502 }
1503 out->offload_thread_blocked = true;
1504 pthread_mutex_unlock(&out->lock);
1505 send_callback = false;
1506 switch(cmd->cmd) {
1507 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001508 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001509 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001510 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001511 send_callback = true;
1512 event = STREAM_CBK_EVENT_WRITE_READY;
1513 break;
1514 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001515 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301516 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001517 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301518 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001519 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301520 if (ret < 0)
1521 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301522 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301523 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001524 compress_drain(out->compr);
1525 else
1526 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301527 if (ret != -ENETRESET) {
1528 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301529 pthread_mutex_lock(&out->lock);
1530 out->send_new_metadata = 1;
1531 out->send_next_track_params = true;
1532 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301533 event = STREAM_CBK_EVENT_DRAIN_READY;
1534 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1535 } else
1536 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001537 break;
1538 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001539 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001540 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001541 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001542 send_callback = true;
1543 event = STREAM_CBK_EVENT_DRAIN_READY;
1544 break;
1545 default:
1546 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1547 break;
1548 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001549 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001550 out->offload_thread_blocked = false;
1551 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001552 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001553 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001554 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001555 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001556 free(cmd);
1557 }
1558
1559 pthread_cond_signal(&out->cond);
1560 while (!list_empty(&out->offload_cmd_list)) {
1561 item = list_head(&out->offload_cmd_list);
1562 list_remove(item);
1563 free(node_to_item(item, struct offload_cmd, node));
1564 }
1565 pthread_mutex_unlock(&out->lock);
1566
1567 return NULL;
1568}
1569
1570static int create_offload_callback_thread(struct stream_out *out)
1571{
1572 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1573 list_init(&out->offload_cmd_list);
1574 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1575 offload_thread_loop, out);
1576 return 0;
1577}
1578
1579static int destroy_offload_callback_thread(struct stream_out *out)
1580{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001581 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001582 stop_compressed_output_l(out);
1583 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1584
1585 pthread_mutex_unlock(&out->lock);
1586 pthread_join(out->offload_thread, (void **) NULL);
1587 pthread_cond_destroy(&out->offload_cond);
1588
1589 return 0;
1590}
1591
Mingming Yin21854652016-04-13 11:54:02 -07001592static bool allow_hdmi_channel_config(struct audio_device *adev,
1593 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001594{
1595 struct listnode *node;
1596 struct audio_usecase *usecase;
1597 bool ret = true;
1598
Mingming Yin21854652016-04-13 11:54:02 -07001599 if (enable_passthru && !audio_extn_passthru_is_enabled()) {
1600 ret = false;
1601 goto exit;
1602 }
1603
1604 if (audio_extn_passthru_is_active()) {
1605 ALOGI("%s: Compress audio passthrough is active,"
1606 "no HDMI config change allowed", __func__);
1607 ret = false;
1608 goto exit;
1609 }
1610
Eric Laurent07eeafd2013-10-06 12:52:49 -07001611 list_for_each(node, &adev->usecase_list) {
1612 usecase = node_to_item(node, struct audio_usecase, list);
1613 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1614 /*
1615 * If voice call is already existing, do not proceed further to avoid
1616 * disabling/enabling both RX and TX devices, CSD calls, etc.
1617 * Once the voice call done, the HDMI channels can be configured to
1618 * max channels of remaining use cases.
1619 */
1620 if (usecase->id == USECASE_VOICE_CALL) {
Mingming Yin21854652016-04-13 11:54:02 -07001621 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001622 __func__);
1623 ret = false;
1624 break;
1625 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Mingming Yin21854652016-04-13 11:54:02 -07001626 if (!enable_passthru) {
1627 ALOGV("%s: multi channel playback is active, "
1628 "no change in HDMI channels", __func__);
1629 ret = false;
1630 break;
1631 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001632 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001633 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin21854652016-04-13 11:54:02 -07001634 if (!enable_passthru) {
1635 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1636 ", no change in HDMI channels", __func__,
1637 usecase->stream.out->channel_mask);
1638 ret = false;
1639 break;
1640 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001641 }
1642 }
1643 }
Mingming Yin21854652016-04-13 11:54:02 -07001644 ALOGV("allow hdmi config %d", ret);
1645exit:
Eric Laurent07eeafd2013-10-06 12:52:49 -07001646 return ret;
1647}
1648
Mingming Yin21854652016-04-13 11:54:02 -07001649static int check_and_set_hdmi_config(struct audio_device *adev,
1650 uint32_t channels,
1651 uint32_t sample_rate,
1652 audio_format_t format,
1653 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001654{
1655 struct listnode *node;
1656 struct audio_usecase *usecase;
Mingming Yin21854652016-04-13 11:54:02 -07001657 int32_t factor = 1;
1658 bool config = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001659
Mingming Yin21854652016-04-13 11:54:02 -07001660 ALOGV("%s channels %d sample_rate %d format:%x enable_passthru:%d",
1661 __func__, channels, sample_rate, format, enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001662
Mingming Yin21854652016-04-13 11:54:02 -07001663 if (channels != adev->cur_hdmi_channels) {
1664 ALOGV("channel does not match current hdmi channels");
1665 config = true;
1666 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001667
Mingming Yin21854652016-04-13 11:54:02 -07001668 if (sample_rate != adev->cur_hdmi_sample_rate) {
1669 ALOGV("sample rate does not match current hdmi sample rate");
1670 config = true;
1671 }
1672
1673 if (format != adev->cur_hdmi_format) {
1674 ALOGV("format does not match current hdmi format");
1675 config = true;
1676 }
1677
1678 /* TBD - add check for bit width */
1679 if (!config) {
1680 ALOGV("No need to config hdmi");
Eric Laurent07eeafd2013-10-06 12:52:49 -07001681 return 0;
1682 }
1683
Mingming Yin21854652016-04-13 11:54:02 -07001684 if (enable_passthru &&
1685 (format == AUDIO_FORMAT_E_AC3)) {
1686 ALOGV("factor 4 for E_AC3 passthru");
1687 factor = 4;
1688 }
1689
1690 platform_set_hdmi_config(adev->platform, channels, factor * sample_rate,
1691 enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001692 adev->cur_hdmi_channels = channels;
Mingming Yin21854652016-04-13 11:54:02 -07001693 adev->cur_hdmi_format = format;
1694 adev->cur_hdmi_sample_rate = sample_rate;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001695
1696 /*
1697 * Deroute all the playback streams routed to HDMI so that
1698 * the back end is deactivated. Note that backend will not
1699 * be deactivated if any one stream is connected to it.
1700 */
1701 list_for_each(node, &adev->usecase_list) {
1702 usecase = node_to_item(node, struct audio_usecase, list);
1703 if (usecase->type == PCM_PLAYBACK &&
1704 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001705 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001706 }
1707 }
1708
Mingming Yin21854652016-04-13 11:54:02 -07001709 bool was_active = audio_extn_keep_alive_is_active();
1710 if (was_active)
1711 audio_extn_keep_alive_stop();
1712
Eric Laurent07eeafd2013-10-06 12:52:49 -07001713 /*
1714 * Enable all the streams disabled above. Now the HDMI backend
1715 * will be activated with new channel configuration
1716 */
1717 list_for_each(node, &adev->usecase_list) {
1718 usecase = node_to_item(node, struct audio_usecase, list);
1719 if (usecase->type == PCM_PLAYBACK &&
1720 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001721 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001722 }
1723 }
1724
Mingming Yin21854652016-04-13 11:54:02 -07001725 if (was_active)
1726 audio_extn_keep_alive_start();
1727
Eric Laurent07eeafd2013-10-06 12:52:49 -07001728 return 0;
1729}
1730
Mingming Yin21854652016-04-13 11:54:02 -07001731/* called with out lock taken */
1732static int check_and_set_hdmi_backend(struct stream_out *out)
1733{
1734 struct audio_device *adev = out->dev;
1735 int ret;
1736 bool enable_passthru = false;
1737
1738 if (!(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL))
1739 return -1;
1740
1741 ALOGV("%s usecase %s out->format:%x out->bit_width:%d", __func__, use_case_table[out->usecase],out->format,out->bit_width);
1742
1743 if (is_offload_usecase(out->usecase) &&
1744 audio_extn_dolby_is_passthrough_stream(out)) {
1745 enable_passthru = true;
1746 }
1747
1748 /* Check if change in HDMI channel config is allowed */
1749 if (!allow_hdmi_channel_config(adev, enable_passthru)) {
1750 return -EPERM;
1751 }
1752
1753 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1754 uint32_t channels;
1755 ALOGV("Offload usecase, enable passthru %d", enable_passthru);
1756
1757 if (enable_passthru) {
1758 audio_extn_passthru_on_start(out);
1759 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1760 }
1761
1762 /* For pass through case, the backend should be configured as stereo */
1763 channels = enable_passthru ? DEFAULT_HDMI_OUT_CHANNELS :
1764 out->compr_config.codec->ch_in;
1765
1766 ret = check_and_set_hdmi_config(adev, channels,
1767 out->sample_rate, out->format,
1768 enable_passthru);
1769 } else
1770 ret = check_and_set_hdmi_config(adev, out->config.channels,
1771 out->config.rate,
1772 out->format,
1773 false);
1774 return ret;
1775}
1776
1777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778static int stop_output_stream(struct stream_out *out)
1779{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301780 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781 struct audio_usecase *uc_info;
1782 struct audio_device *adev = out->dev;
1783
Eric Laurent994a6932013-07-17 11:51:42 -07001784 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001785 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001786 uc_info = get_usecase_from_list(adev, out->usecase);
1787 if (uc_info == NULL) {
1788 ALOGE("%s: Could not find the usecase (%d) in the list",
1789 __func__, out->usecase);
1790 return -EINVAL;
1791 }
1792
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001793 if (is_offload_usecase(out->usecase) &&
Mingming Yin21854652016-04-13 11:54:02 -07001794 !(audio_extn_dolby_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001795 if (adev->visualizer_stop_output != NULL)
1796 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001797
1798 audio_extn_dts_remove_state_notifier_node(out->usecase);
1799
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001800 if (adev->offload_effects_stop_output != NULL)
1801 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1802 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001803
Eric Laurent150dbfe2013-02-27 14:31:02 -08001804 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001805 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001806
1807 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001808 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001810 list_remove(&uc_info->list);
1811 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001813 if (is_offload_usecase(out->usecase) &&
Mingming Yin21854652016-04-13 11:54:02 -07001814 (audio_extn_dolby_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001815 ALOGV("Disable passthrough , reset mixer to pcm");
1816 /* NO_PASSTHROUGH */
1817 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001818
1819 /* Must be called after removing the usecase from list */
1820 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1821 check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
1822 DEFAULT_HDMI_OUT_SAMPLE_RATE,
1823 DEFAULT_HDMI_OUT_FORMAT,
1824 false);
1825 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001826 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1827 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001828
Eric Laurent994a6932013-07-17 11:51:42 -07001829 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830 return ret;
1831}
1832
1833int start_output_stream(struct stream_out *out)
1834{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001835 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001836 struct audio_usecase *uc_info;
1837 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301838 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001840 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1841 ret = -EINVAL;
1842 goto error_config;
1843 }
1844
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301845 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1846 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1847 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301848
Naresh Tanniru80659832014-06-04 18:17:56 +05301849 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301850 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301851 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301852 goto error_config;
1853 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301854
Eric Laurentb23d5282013-05-14 15:27:20 -07001855 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856 if (out->pcm_device_id < 0) {
1857 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1858 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001859 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001860 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861 }
1862
1863 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001864
1865 if (!uc_info) {
1866 ret = -ENOMEM;
1867 goto error_config;
1868 }
1869
Mingming Yin21854652016-04-13 11:54:02 -07001870 /* This must be called before adding this usecase to the list */
1871 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1872 /* This call can fail if compress pass thru is already active */
1873 check_and_set_hdmi_backend(out);
1874 }
1875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001876 uc_info->id = out->usecase;
1877 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001878 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001879 uc_info->devices = out->devices;
1880 uc_info->in_snd_device = SND_DEVICE_NONE;
1881 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001882 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301884 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1885 adev->perf_lock_opts,
1886 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001887 select_devices(adev, out->usecase);
1888
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001889 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1890 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001891 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001892 unsigned int flags = PCM_OUT;
1893 unsigned int pcm_open_retry_count = 0;
1894 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1895 flags |= PCM_MMAP | PCM_NOIRQ;
1896 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1897 } else
1898 flags |= PCM_MONOTONIC;
1899
1900 while (1) {
1901 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1902 flags, &out->config);
1903 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1904 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1905 if (out->pcm != NULL) {
1906 pcm_close(out->pcm);
1907 out->pcm = NULL;
1908 }
1909 if (pcm_open_retry_count-- == 0) {
1910 ret = -EIO;
1911 goto error_open;
1912 }
1913 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1914 continue;
1915 }
1916 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001917 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001918
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001919 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1920 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001921
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001922 ALOGV("%s: pcm_prepare", __func__);
1923 if (pcm_is_ready(out->pcm)) {
1924 ret = pcm_prepare(out->pcm);
1925 if (ret < 0) {
1926 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1927 pcm_close(out->pcm);
1928 out->pcm = NULL;
1929 goto error_open;
1930 }
1931 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001932 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001933 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1934 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001935 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001936 out->compr = compress_open(adev->snd_card,
1937 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001938 COMPRESS_IN, &out->compr_config);
1939 if (out->compr && !is_compress_ready(out->compr)) {
1940 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1941 compress_close(out->compr);
1942 out->compr = NULL;
1943 ret = -EIO;
1944 goto error_open;
1945 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301946 /* compress_open sends params of the track, so reset the flag here */
1947 out->is_compr_metadata_avail = false;
1948
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001949 if (out->offload_callback)
1950 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001951
Fred Oh3f43e742015-03-04 18:42:34 -08001952 /* Since small bufs uses blocking writes, a write will be blocked
1953 for the default max poll time (20s) in the event of an SSR.
1954 Reduce the poll time to observe and deal with SSR faster.
1955 */
1956 if (out->use_small_bufs) {
1957 compress_set_max_poll_wait(out->compr, 1000);
1958 }
1959
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001960 audio_extn_dts_create_state_notifier_node(out->usecase);
1961 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1962 popcount(out->channel_mask),
1963 out->playback_started);
1964
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001965#ifdef DS1_DOLBY_DDP_ENABLED
1966 if (audio_extn_is_dolby_format(out->format))
1967 audio_extn_dolby_send_ddp_endp_params(adev);
1968#endif
Mingming Yin21854652016-04-13 11:54:02 -07001969 if (!(audio_extn_dolby_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001970 if (adev->visualizer_start_output != NULL)
1971 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1972 if (adev->offload_effects_start_output != NULL)
1973 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001974 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001975 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301977 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001978 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001981error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301982 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001984error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301985 /*
1986 * sleep 50ms to allow sufficient time for kernel
1987 * drivers to recover incases like SSR.
1988 */
1989 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001990 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991}
1992
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993static int check_input_parameters(uint32_t sample_rate,
1994 audio_format_t format,
1995 int channel_count)
1996{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001997 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001998
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001999 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002000 !voice_extn_compress_voip_is_format_supported(format) &&
2001 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002002
2003 switch (channel_count) {
2004 case 1:
2005 case 2:
2006 case 6:
2007 break;
2008 default:
2009 ret = -EINVAL;
2010 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011
2012 switch (sample_rate) {
2013 case 8000:
2014 case 11025:
2015 case 12000:
2016 case 16000:
2017 case 22050:
2018 case 24000:
2019 case 32000:
2020 case 44100:
2021 case 48000:
2022 break;
2023 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002024 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002025 }
2026
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002027 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028}
2029
2030static size_t get_input_buffer_size(uint32_t sample_rate,
2031 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002032 int channel_count,
2033 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002034{
2035 size_t size = 0;
2036
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002037 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2038 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002039
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002040 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002041 if (is_low_latency)
2042 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002043 /* ToDo: should use frame_size computed based on the format and
2044 channel_count here. */
2045 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002046
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002047 /* make sure the size is multiple of 32 bytes
2048 * At 48 kHz mono 16-bit PCM:
2049 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2050 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2051 */
2052 size += 0x1f;
2053 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002054
2055 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056}
2057
2058static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2059{
2060 struct stream_out *out = (struct stream_out *)stream;
2061
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002062 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063}
2064
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002065static int out_set_sample_rate(struct audio_stream *stream __unused,
2066 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002067{
2068 return -ENOSYS;
2069}
2070
2071static size_t out_get_buffer_size(const struct audio_stream *stream)
2072{
2073 struct stream_out *out = (struct stream_out *)stream;
2074
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002075 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002076 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002077 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2078 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002079
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002080 return out->config.period_size *
2081 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002082}
2083
2084static uint32_t out_get_channels(const struct audio_stream *stream)
2085{
2086 struct stream_out *out = (struct stream_out *)stream;
2087
2088 return out->channel_mask;
2089}
2090
2091static audio_format_t out_get_format(const struct audio_stream *stream)
2092{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002093 struct stream_out *out = (struct stream_out *)stream;
2094
2095 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096}
2097
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002098static int out_set_format(struct audio_stream *stream __unused,
2099 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100{
2101 return -ENOSYS;
2102}
2103
2104static int out_standby(struct audio_stream *stream)
2105{
2106 struct stream_out *out = (struct stream_out *)stream;
2107 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002108
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302109 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2110 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002111 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2112 /* Ignore standby in case of voip call because the voip output
2113 * stream is closed in adev_close_output_stream()
2114 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302115 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002116 return 0;
2117 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002119 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002121 if (adev->adm_deregister_stream)
2122 adev->adm_deregister_stream(adev->adm_data, out->handle);
2123
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002124 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002126 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002127 if (out->pcm) {
2128 pcm_close(out->pcm);
2129 out->pcm = NULL;
2130 }
2131 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002132 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002133 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302134 out->send_next_track_params = false;
2135 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002136 out->gapless_mdata.encoder_delay = 0;
2137 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002138 if (out->compr != NULL) {
2139 compress_close(out->compr);
2140 out->compr = NULL;
2141 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002142 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002144 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002145 }
2146 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302147 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002148 return 0;
2149}
2150
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002151static int out_dump(const struct audio_stream *stream __unused,
2152 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153{
2154 return 0;
2155}
2156
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002157static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2158{
2159 int ret = 0;
2160 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002161
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002162 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002163 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002164 return -EINVAL;
2165 }
2166
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302167 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002168
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002169 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2170 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302171 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002172 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002173 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2174 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302175 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002176 }
2177
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002178 ALOGV("%s new encoder delay %u and padding %u", __func__,
2179 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2180
2181 return 0;
2182}
2183
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002184static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2185{
2186 return out == adev->primary_output || out == adev->voice_tx_output;
2187}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2190{
2191 struct stream_out *out = (struct stream_out *)stream;
2192 struct audio_device *adev = out->dev;
2193 struct str_parms *parms;
2194 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002195 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196
sangwoobc677242013-08-08 16:53:43 +09002197 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002198 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002199 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302200 if (!parms)
2201 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002202 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2203 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002204 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002205 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002206 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002208 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302209 * When HDMI cable is unplugged/usb hs is disconnected the
2210 * music playback is paused and the policy manager sends routing=0
2211 * But the audioflingercontinues to write data until standby time
2212 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002213 * Avoid this by routing audio to speaker until standby.
2214 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302215 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2216 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002217 val == AUDIO_DEVICE_NONE) {
Mingming Yin21854652016-04-13 11:54:02 -07002218 if (!audio_extn_dolby_is_passthrough_stream(out))
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08002219 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002220 }
2221
2222 /*
2223 * select_devices() call below switches all the usecases on the same
2224 * backend to the new device. Refer to check_usecases_codec_backend() in
2225 * the select_devices(). But how do we undo this?
2226 *
2227 * For example, music playback is active on headset (deep-buffer usecase)
2228 * and if we go to ringtones and select a ringtone, low-latency usecase
2229 * will be started on headset+speaker. As we can't enable headset+speaker
2230 * and headset devices at the same time, select_devices() switches the music
2231 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2232 * So when the ringtone playback is completed, how do we undo the same?
2233 *
2234 * We are relying on the out_set_parameters() call on deep-buffer output,
2235 * once the ringtone playback is ended.
2236 * NOTE: We should not check if the current devices are same as new devices.
2237 * Because select_devices() must be called to switch back the music
2238 * playback to headset.
2239 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002240 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002241 out->devices = val;
2242
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302243 if (!out->standby) {
2244 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2245 adev->perf_lock_opts,
2246 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002247 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302248 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2249 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002250
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002251 if (output_drives_call(adev, out)) {
2252 if(!voice_is_in_call(adev)) {
2253 if (adev->mode == AUDIO_MODE_IN_CALL) {
2254 adev->current_call_output = out;
2255 ret = voice_start_call(adev);
2256 }
2257 } else {
2258 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002259 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002260 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002261 }
2262 }
2263
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002264 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002265 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002266 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002267
2268 if (out == adev->primary_output) {
2269 pthread_mutex_lock(&adev->lock);
2270 audio_extn_set_parameters(adev, parms);
2271 pthread_mutex_unlock(&adev->lock);
2272 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002273 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002274 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002275 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002276
2277 audio_extn_dts_create_state_notifier_node(out->usecase);
2278 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2279 popcount(out->channel_mask),
2280 out->playback_started);
2281
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002282 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002283 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002284
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002285 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302286error:
Eric Laurent994a6932013-07-17 11:51:42 -07002287 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002288 return ret;
2289}
2290
2291static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2292{
2293 struct stream_out *out = (struct stream_out *)stream;
2294 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002295 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002296 char value[256];
2297 struct str_parms *reply = str_parms_create();
2298 size_t i, j;
2299 int ret;
2300 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002301
2302 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002303 if (reply) {
2304 str_parms_destroy(reply);
2305 }
2306 if (query) {
2307 str_parms_destroy(query);
2308 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002309 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2310 return NULL;
2311 }
2312
Eric Laurent994a6932013-07-17 11:51:42 -07002313 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2315 if (ret >= 0) {
2316 value[0] = '\0';
2317 i = 0;
2318 while (out->supported_channel_masks[i] != 0) {
2319 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2320 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2321 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002322 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002323 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002324 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002325 first = false;
2326 break;
2327 }
2328 }
2329 i++;
2330 }
2331 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2332 str = str_parms_to_str(reply);
2333 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002334 voice_extn_out_get_parameters(out, query, reply);
2335 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002336 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002337 free(str);
2338 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002339 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002340 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002341
Alexy Joseph62142aa2015-11-16 15:10:34 -08002342
2343 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2344 if (ret >= 0) {
2345 value[0] = '\0';
2346 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2347 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302348 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002349 } else {
2350 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302351 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002352 }
2353 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002354 if (str)
2355 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002356 str = str_parms_to_str(reply);
2357 }
2358
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002359 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2360 if (ret >= 0) {
2361 value[0] = '\0';
2362 i = 0;
2363 first = true;
2364 while (out->supported_formats[i] != 0) {
2365 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2366 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2367 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002368 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002369 }
2370 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2371 first = false;
2372 break;
2373 }
2374 }
2375 i++;
2376 }
2377 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002378 if (str)
2379 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002380 str = str_parms_to_str(reply);
2381 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002382
2383 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2384 if (ret >= 0) {
2385 value[0] = '\0';
2386 i = 0;
2387 first = true;
2388 while (out->supported_sample_rates[i] != 0) {
2389 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2390 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2391 if (!first) {
2392 strlcat(value, "|", sizeof(value));
2393 }
2394 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2395 first = false;
2396 break;
2397 }
2398 }
2399 i++;
2400 }
2401 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2402 if (str)
2403 free(str);
2404 str = str_parms_to_str(reply);
2405 }
2406
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002407 str_parms_destroy(query);
2408 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002409 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002410 return str;
2411}
2412
2413static uint32_t out_get_latency(const struct audio_stream_out *stream)
2414{
2415 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002416 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002417
Alexy Josephaa54c872014-12-03 02:46:47 -08002418 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002419 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002420 } else {
2421 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002422 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002423 }
2424
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302425 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002426 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002427}
2428
2429static int out_set_volume(struct audio_stream_out *stream, float left,
2430 float right)
2431{
Eric Laurenta9024de2013-04-04 09:19:12 -07002432 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002433 int volume[2];
2434
Eric Laurenta9024de2013-04-04 09:19:12 -07002435 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2436 /* only take left channel into account: the API is for stereo anyway */
2437 out->muted = (left == 0.0f);
2438 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002439 } else if (is_offload_usecase(out->usecase)) {
Mingming Yin21854652016-04-13 11:54:02 -07002440 if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002441 /*
2442 * Set mute or umute on HDMI passthrough stream.
2443 * Only take left channel into account.
2444 * Mute is 0 and unmute 1
2445 */
2446 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2447 } else {
2448 char mixer_ctl_name[128];
2449 struct audio_device *adev = out->dev;
2450 struct mixer_ctl *ctl;
2451 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002452 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002453
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002454 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2455 "Compress Playback %d Volume", pcm_device_id);
2456 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2457 if (!ctl) {
2458 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2459 __func__, mixer_ctl_name);
2460 return -EINVAL;
2461 }
2462 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2463 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2464 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2465 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002467 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002468
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469 return -ENOSYS;
2470}
2471
2472static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2473 size_t bytes)
2474{
2475 struct stream_out *out = (struct stream_out *)stream;
2476 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302477 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002478 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002479
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002480 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302481
Naresh Tanniru80659832014-06-04 18:17:56 +05302482 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002483
Ashish Jainbbce4322016-02-16 13:25:27 +05302484 if (is_offload_usecase(out->usecase)) {
2485 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302486 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2487 pthread_mutex_unlock(&out->lock);
2488 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302489 } else {
2490 /* increase written size during SSR to avoid mismatch
2491 * with the written frames count in AF
2492 */
2493 out->written += bytes / (out->config.channels * sizeof(short));
2494 ALOGD(" %s: sound card is not active/SSR state", __func__);
2495 ret= -EIO;
2496 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302497 }
2498 }
2499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002501 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002502 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002503 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2504 ret = voice_extn_compress_voip_start_output_stream(out);
2505 else
2506 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002507 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002508 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002510 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 goto exit;
2512 }
vivek mehta446c3962015-09-14 10:57:35 -07002513 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002514 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516
Ashish Jain81eb2a82015-05-13 10:52:34 +05302517 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002518 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302519 adev->is_channel_status_set = true;
2520 }
2521
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002522 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002523 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002524 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002525 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002526 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2527 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302528 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2529 ALOGD("copl(%p):send next track params in gapless", out);
2530 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2531 out->send_next_track_params = false;
2532 out->is_compr_metadata_avail = false;
2533 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002534 }
2535
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002536 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302537 if (ret < 0)
2538 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302539 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002540 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302541 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002542 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302543 } else if (-ENETRESET == ret) {
2544 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2545 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2546 pthread_mutex_unlock(&out->lock);
2547 out_standby(&out->stream.common);
2548 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002549 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302550 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002551 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002552 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002553 out->playback_started = 1;
2554 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002555
2556 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2557 popcount(out->channel_mask),
2558 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002559 }
2560 pthread_mutex_unlock(&out->lock);
2561 return ret;
2562 } else {
2563 if (out->pcm) {
2564 if (out->muted)
2565 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002566
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302567 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002568
2569 if (adev->adm_request_focus)
2570 adev->adm_request_focus(adev->adm_data, out->handle);
2571
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002572 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2573 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2574 else
2575 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002576
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302577 if (ret < 0)
2578 ret = -errno;
2579 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002580 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002581
2582 if (adev->adm_abandon_focus)
2583 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002584 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585 }
2586
2587exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302588 /* ToDo: There may be a corner case when SSR happens back to back during
2589 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302590 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302591 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302592 }
2593
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594 pthread_mutex_unlock(&out->lock);
2595
2596 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002597 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002598 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302599 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302600 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302601 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302602 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302603 out->standby = true;
2604 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002605 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302606 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302607 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608 }
2609 return bytes;
2610}
2611
2612static int out_get_render_position(const struct audio_stream_out *stream,
2613 uint32_t *dsp_frames)
2614{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002615 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302616 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002617
2618 if (dsp_frames == NULL)
2619 return -EINVAL;
2620
2621 *dsp_frames = 0;
2622 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002623 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002624 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002625 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302626 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002627 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302628 if (ret < 0)
2629 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002630 ALOGVV("%s rendered frames %d sample_rate %d",
2631 __func__, *dsp_frames, out->sample_rate);
2632 }
2633 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302634 if (-ENETRESET == ret) {
2635 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2636 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2637 return -EINVAL;
2638 } else if(ret < 0) {
2639 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2640 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302641 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2642 /*
2643 * Handle corner case where compress session is closed during SSR
2644 * and timestamp is queried
2645 */
2646 ALOGE(" ERROR: sound card not active, return error");
2647 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302648 } else {
2649 return 0;
2650 }
Zhou Song32a556e2015-05-05 10:46:56 +08002651 } else if (audio_is_linear_pcm(out->format)) {
2652 *dsp_frames = out->written;
2653 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002654 } else
2655 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656}
2657
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002658static int out_add_audio_effect(const struct audio_stream *stream __unused,
2659 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660{
2661 return 0;
2662}
2663
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002664static int out_remove_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_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2671 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002672{
2673 return -EINVAL;
2674}
2675
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002676static int out_get_presentation_position(const struct audio_stream_out *stream,
2677 uint64_t *frames, struct timespec *timestamp)
2678{
2679 struct stream_out *out = (struct stream_out *)stream;
2680 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002681 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002682
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002683 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002684
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002685 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002686 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302687 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002688 &out->sample_rate);
2689 ALOGVV("%s rendered frames %ld sample_rate %d",
2690 __func__, dsp_frames, out->sample_rate);
2691 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302692 if (ret < 0)
2693 ret = -errno;
2694 if (-ENETRESET == ret) {
2695 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2696 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2697 ret = -EINVAL;
2698 } else
2699 ret = 0;
2700
Eric Laurent949a0892013-09-20 09:20:13 -07002701 /* this is the best we can do */
2702 clock_gettime(CLOCK_MONOTONIC, timestamp);
2703 }
2704 } else {
2705 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002706 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002707 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2708 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002709 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002710 // This adjustment accounts for buffering after app processor.
2711 // It is based on estimated DSP latency per use case, rather than exact.
2712 signed_frames -=
2713 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2714
Eric Laurent949a0892013-09-20 09:20:13 -07002715 // It would be unusual for this value to be negative, but check just in case ...
2716 if (signed_frames >= 0) {
2717 *frames = signed_frames;
2718 ret = 0;
2719 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002720 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302721 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2722 *frames = out->written;
2723 clock_gettime(CLOCK_MONOTONIC, timestamp);
2724 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002725 }
2726 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002727 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002728 return ret;
2729}
2730
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002731static int out_set_callback(struct audio_stream_out *stream,
2732 stream_callback_t callback, void *cookie)
2733{
2734 struct stream_out *out = (struct stream_out *)stream;
2735
2736 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002737 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002738 out->offload_callback = callback;
2739 out->offload_cookie = cookie;
2740 pthread_mutex_unlock(&out->lock);
2741 return 0;
2742}
2743
2744static int out_pause(struct audio_stream_out* stream)
2745{
2746 struct stream_out *out = (struct stream_out *)stream;
2747 int status = -ENOSYS;
2748 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002749 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002750 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002751 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002752 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302753 struct audio_device *adev = out->dev;
2754 int snd_scard_state = get_snd_card_state(adev);
2755
2756 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2757 status = compress_pause(out->compr);
2758
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002759 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002760
Mingming Yin21854652016-04-13 11:54:02 -07002761 if (audio_extn_passthru_is_active()) {
2762 ALOGV("offload use case, pause passthru");
2763 audio_extn_passthru_on_pause(out);
2764 }
2765
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302766 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002767 audio_extn_dts_notify_playback_state(out->usecase, 0,
2768 out->sample_rate, popcount(out->channel_mask),
2769 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002770 }
2771 pthread_mutex_unlock(&out->lock);
2772 }
2773 return status;
2774}
2775
2776static int out_resume(struct audio_stream_out* stream)
2777{
2778 struct stream_out *out = (struct stream_out *)stream;
2779 int status = -ENOSYS;
2780 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002781 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002782 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002783 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002784 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002785 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302786 struct audio_device *adev = out->dev;
2787 int snd_scard_state = get_snd_card_state(adev);
2788
Mingming Yin21854652016-04-13 11:54:02 -07002789 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
2790 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2791 pthread_mutex_lock(&out->dev->lock);
2792 ALOGV("offload resume, check and set hdmi backend again");
2793 check_and_set_hdmi_backend(out);
2794 pthread_mutex_unlock(&out->dev->lock);
2795 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302796 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07002797 }
2798 if (!status) {
2799 out->offload_state = OFFLOAD_STATE_PLAYING;
2800 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302801 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002802 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2803 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002804 }
2805 pthread_mutex_unlock(&out->lock);
2806 }
2807 return status;
2808}
2809
2810static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2811{
2812 struct stream_out *out = (struct stream_out *)stream;
2813 int status = -ENOSYS;
2814 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002815 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002816 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002817 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2818 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2819 else
2820 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2821 pthread_mutex_unlock(&out->lock);
2822 }
2823 return status;
2824}
2825
2826static int out_flush(struct audio_stream_out* stream)
2827{
2828 struct stream_out *out = (struct stream_out *)stream;
2829 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002830 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002831 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002832 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002833 stop_compressed_output_l(out);
2834 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002835 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002836 return 0;
2837 }
2838 return -ENOSYS;
2839}
2840
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002841/** audio_stream_in implementation **/
2842static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2843{
2844 struct stream_in *in = (struct stream_in *)stream;
2845
2846 return in->config.rate;
2847}
2848
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002849static int in_set_sample_rate(struct audio_stream *stream __unused,
2850 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002851{
2852 return -ENOSYS;
2853}
2854
2855static size_t in_get_buffer_size(const struct audio_stream *stream)
2856{
2857 struct stream_in *in = (struct stream_in *)stream;
2858
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002859 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2860 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002861 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2862 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002863
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002864 return in->config.period_size *
2865 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002866}
2867
2868static uint32_t in_get_channels(const struct audio_stream *stream)
2869{
2870 struct stream_in *in = (struct stream_in *)stream;
2871
2872 return in->channel_mask;
2873}
2874
2875static audio_format_t in_get_format(const struct audio_stream *stream)
2876{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002877 struct stream_in *in = (struct stream_in *)stream;
2878
2879 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880}
2881
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002882static int in_set_format(struct audio_stream *stream __unused,
2883 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002884{
2885 return -ENOSYS;
2886}
2887
2888static int in_standby(struct audio_stream *stream)
2889{
2890 struct stream_in *in = (struct stream_in *)stream;
2891 struct audio_device *adev = in->dev;
2892 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302893 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2894 stream, in->usecase, use_case_table[in->usecase]);
2895
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002896 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2897 /* Ignore standby in case of voip call because the voip input
2898 * stream is closed in adev_close_input_stream()
2899 */
2900 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2901 return status;
2902 }
2903
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002904 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002905 if (!in->standby && in->is_st_session) {
2906 ALOGD("%s: sound trigger pcm stop lab", __func__);
2907 audio_extn_sound_trigger_stop_lab(in);
2908 in->standby = 1;
2909 }
2910
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002911 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002912 if (adev->adm_deregister_stream)
2913 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2914
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002915 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002916 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002917 if (in->pcm) {
2918 pcm_close(in->pcm);
2919 in->pcm = NULL;
2920 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002921 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002922 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002923 }
2924 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002925 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002926 return status;
2927}
2928
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002929static int in_dump(const struct audio_stream *stream __unused,
2930 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002931{
2932 return 0;
2933}
2934
2935static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2936{
2937 struct stream_in *in = (struct stream_in *)stream;
2938 struct audio_device *adev = in->dev;
2939 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002940 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002941 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302943 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944 parms = str_parms_create_str(kvpairs);
2945
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302946 if (!parms)
2947 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002948 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002949 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002950
2951 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2952 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002953 val = atoi(value);
2954 /* no audio source uses val == 0 */
2955 if ((in->source != val) && (val != 0)) {
2956 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002957 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2958 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2959 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08002960 (in->config.rate == 8000 || in->config.rate == 16000 ||
2961 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002962 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002963 err = voice_extn_compress_voip_open_input_stream(in);
2964 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002965 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002966 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002967 }
2968 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002969 }
2970 }
2971
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002972 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2973 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002975 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976 in->device = val;
2977 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002978 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002979 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980 }
2981 }
2982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002984 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985
2986 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302987error:
Eric Laurent994a6932013-07-17 11:51:42 -07002988 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 return ret;
2990}
2991
2992static char* in_get_parameters(const struct audio_stream *stream,
2993 const char *keys)
2994{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002995 struct stream_in *in = (struct stream_in *)stream;
2996 struct str_parms *query = str_parms_create_str(keys);
2997 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002998 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002999
3000 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003001 if (reply) {
3002 str_parms_destroy(reply);
3003 }
3004 if (query) {
3005 str_parms_destroy(query);
3006 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003007 ALOGE("in_get_parameters: failed to create query or reply");
3008 return NULL;
3009 }
3010
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003011 ALOGV("%s: enter: keys - %s", __func__, keys);
3012
3013 voice_extn_in_get_parameters(in, query, reply);
3014
3015 str = str_parms_to_str(reply);
3016 str_parms_destroy(query);
3017 str_parms_destroy(reply);
3018
3019 ALOGV("%s: exit: returns - %s", __func__, str);
3020 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021}
3022
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003023static int in_set_gain(struct audio_stream_in *stream __unused,
3024 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025{
3026 return 0;
3027}
3028
3029static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3030 size_t bytes)
3031{
3032 struct stream_in *in = (struct stream_in *)stream;
3033 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303034 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303035 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003037 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303038
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003039 if (in->is_st_session) {
3040 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3041 /* Read from sound trigger HAL */
3042 audio_extn_sound_trigger_read(in, buffer, bytes);
3043 pthread_mutex_unlock(&in->lock);
3044 return bytes;
3045 }
3046
Ashish Jainbbce4322016-02-16 13:25:27 +05303047 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003048 ALOGD(" %s: sound card is not active/SSR state", __func__);
3049 ret= -EIO;;
3050 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303051 }
3052
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003054 pthread_mutex_lock(&adev->lock);
3055 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3056 ret = voice_extn_compress_voip_start_input_stream(in);
3057 else
3058 ret = start_input_stream(in);
3059 pthread_mutex_unlock(&adev->lock);
3060 if (ret != 0) {
3061 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062 }
3063 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003064 if (adev->adm_register_input_stream)
3065 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003068 if (adev->adm_request_focus)
3069 adev->adm_request_focus(adev->adm_data, in->capture_handle);
3070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003071 if (in->pcm) {
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003072 if (audio_extn_ssr_get_stream() == in)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003073 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07003074 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
3075 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003076 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
3077 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003078 else
3079 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303080 if (ret < 0)
3081 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082 }
3083
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003084 if (adev->adm_abandon_focus)
3085 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
3086
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003087 /*
3088 * Instead of writing zeroes here, we could trust the hardware
3089 * to always provide zeroes when muted.
3090 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303091 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3092 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003093 memset(buffer, 0, bytes);
3094
3095exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303096 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303097 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003098 if (-ENETRESET == ret)
3099 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101 pthread_mutex_unlock(&in->lock);
3102
3103 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303104 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303105 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303106 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303107 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303108 in->standby = true;
3109 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303110 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003112 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303113 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303114 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003115 }
3116 return bytes;
3117}
3118
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003119static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120{
3121 return 0;
3122}
3123
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003124static int add_remove_audio_effect(const struct audio_stream *stream,
3125 effect_handle_t effect,
3126 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003128 struct stream_in *in = (struct stream_in *)stream;
3129 int status = 0;
3130 effect_descriptor_t desc;
3131
3132 status = (*effect)->get_descriptor(effect, &desc);
3133 if (status != 0)
3134 return status;
3135
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003136 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003137 pthread_mutex_lock(&in->dev->lock);
3138 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3139 in->enable_aec != enable &&
3140 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3141 in->enable_aec = enable;
3142 if (!in->standby)
3143 select_devices(in->dev, in->usecase);
3144 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003145 if (in->enable_ns != enable &&
3146 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3147 in->enable_ns = enable;
3148 if (!in->standby)
3149 select_devices(in->dev, in->usecase);
3150 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003151 pthread_mutex_unlock(&in->dev->lock);
3152 pthread_mutex_unlock(&in->lock);
3153
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154 return 0;
3155}
3156
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003157static int in_add_audio_effect(const struct audio_stream *stream,
3158 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159{
Eric Laurent994a6932013-07-17 11:51:42 -07003160 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003161 return add_remove_audio_effect(stream, effect, true);
3162}
3163
3164static int in_remove_audio_effect(const struct audio_stream *stream,
3165 effect_handle_t effect)
3166{
Eric Laurent994a6932013-07-17 11:51:42 -07003167 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003168 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169}
3170
3171static int adev_open_output_stream(struct audio_hw_device *dev,
3172 audio_io_handle_t handle,
3173 audio_devices_t devices,
3174 audio_output_flags_t flags,
3175 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003176 struct audio_stream_out **stream_out,
3177 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003178{
3179 struct audio_device *adev = (struct audio_device *)dev;
3180 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303181 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003182 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003183
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003184 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303185
3186 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3187 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003188 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303189 return -EINVAL;
3190 }
3191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3193
Mingming Yin3a941d42016-02-17 18:08:05 -08003194 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3195 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303196 devices, flags, &out->stream);
3197
3198
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003199 if (!out) {
3200 return -ENOMEM;
3201 }
3202
Haynes Mathew George204045b2015-02-25 20:32:03 -08003203 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003204 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003205 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003207 if (devices == AUDIO_DEVICE_NONE)
3208 devices = AUDIO_DEVICE_OUT_SPEAKER;
3209
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003210 out->flags = flags;
3211 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003212 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003213 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003214 out->sample_rate = config->sample_rate;
3215 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3216 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003217 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003218 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003219 out->non_blocking = 0;
3220 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221
Mingming Yin3a941d42016-02-17 18:08:05 -08003222 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3223 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3224 pthread_mutex_lock(&adev->lock);
3225 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3226 ret = read_hdmi_sink_caps(out);
3227 pthread_mutex_unlock(&adev->lock);
3228 if (ret != 0) {
3229 if (ret == -ENOSYS) {
3230 /* ignore and go with default */
3231 ret = 0;
3232 } else {
3233 ALOGE("error reading hdmi sink caps");
3234 goto error_open;
3235 }
3236 }
3237 }
3238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003239 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003240 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303241 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3242 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003243 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3244 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3245
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003246 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003247 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3248 /*
3249 * Do not handle stereo output in Multi-channel cases
3250 * Stereo case is handled in normal playback path
3251 */
3252 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3253 ret = AUDIO_CHANNEL_OUT_STEREO;
3254 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003255
3256 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3257 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003258 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003259 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003260 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003261
3262 if (config->sample_rate == 0)
3263 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3264 if (config->channel_mask == 0)
3265 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003266 if (config->format == 0)
3267 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003268
3269 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003270 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003271 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3273 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003275 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003277 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3278 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003279 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003280 ret = voice_extn_compress_voip_open_output_stream(out);
3281 if (ret != 0) {
3282 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3283 __func__, ret);
3284 goto error_open;
3285 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003286 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3287 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3288
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003289 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3290 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3291 ALOGE("%s: Unsupported Offload information", __func__);
3292 ret = -EINVAL;
3293 goto error_open;
3294 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003295
Mingming Yin3a941d42016-02-17 18:08:05 -08003296 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003297 if(config->offload_info.format == 0)
3298 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003299 if (config->offload_info.sample_rate == 0)
3300 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003301 }
3302
Mingming Yin90310102013-11-13 16:57:00 -08003303 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003304 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003305 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003306 ret = -EINVAL;
3307 goto error_open;
3308 }
3309
3310 out->compr_config.codec = (struct snd_codec *)
3311 calloc(1, sizeof(struct snd_codec));
3312
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003313 if (!out->compr_config.codec) {
3314 ret = -ENOMEM;
3315 goto error_open;
3316 }
3317
vivek mehta0ea887a2015-08-26 14:01:20 -07003318 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003319 out->usecase = get_offload_usecase(adev, true);
3320 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003321 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003322 out->stream.set_callback = out_set_callback;
3323 out->stream.pause = out_pause;
3324 out->stream.resume = out_resume;
3325 out->stream.drain = out_drain;
3326 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003327 out->usecase = get_offload_usecase(adev, false);
3328 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003329 }
vivek mehta446c3962015-09-14 10:57:35 -07003330
3331 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003332 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3333 config->format == 0 && config->sample_rate == 0 &&
3334 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003335 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003336 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3337 } else {
3338 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3339 ret = -EEXIST;
3340 goto error_open;
3341 }
vivek mehta446c3962015-09-14 10:57:35 -07003342 }
3343
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003344 if (config->offload_info.channel_mask)
3345 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003346 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003347 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003348 config->offload_info.channel_mask = config->channel_mask;
3349 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003350 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003351 out->sample_rate = config->offload_info.sample_rate;
3352
Mingming Yin3ee55c62014-08-04 14:23:35 -07003353 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003354
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003355 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003356 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003357 audio_extn_dolby_get_snd_codec_id(adev, out,
3358 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003359 else
3360 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003361 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003362
3363 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3364 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003365 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003366 platform_get_pcm_offload_buffer_size(&config->offload_info);
Mingming Yin21854652016-04-13 11:54:02 -07003367 } else if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003368 out->compr_config.fragment_size =
3369 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003370 } else {
3371 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003372 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003373 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003374 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3375 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003376 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003377 out->compr_config.codec->bit_rate =
3378 config->offload_info.bit_rate;
3379 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003380 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003381 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303382 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003383 /*TODO: Do we need to change it for passthrough */
3384 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003385
Manish Dewangana6fc5442015-08-24 20:30:31 +05303386 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3387 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3388 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3389 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003390 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3391 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003392 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003393 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003394 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3395 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003396
Mingming Yin3ee55c62014-08-04 14:23:35 -07003397 if (out->bit_width == 24) {
3398 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3399 }
3400
Amit Shekhar6f461b12014-08-01 14:52:58 -07003401 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303402 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003403
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003404 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3405 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003406
Mingming Yin497419f2015-07-01 16:57:32 -07003407 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003408 //this flag is set from framework only if its for PCM formats
3409 //no need to check for PCM format again
3410 out->non_blocking = 0;
3411 out->use_small_bufs = true;
3412 ALOGI("Keep write blocking for small buff: non_blockling %d",
3413 out->non_blocking);
3414 }
3415
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003416 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303417 out->send_next_track_params = false;
3418 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003419 out->offload_state = OFFLOAD_STATE_IDLE;
3420 out->playback_started = 0;
3421
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003422 audio_extn_dts_create_state_notifier_node(out->usecase);
3423
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003424 create_offload_callback_thread(out);
3425 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3426 __func__, config->offload_info.version,
3427 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003428 //Decide if we need to use gapless mode by default
Mingming Yin21854652016-04-13 11:54:02 -07003429 if (!audio_extn_dolby_is_passthrough_stream(out)) {
3430 ALOGV("%s: don't enable gapless for passthrough", __func__);
3431 check_and_set_gapless_mode(adev);
3432 }
3433
3434 if (audio_extn_dolby_is_passthrough_stream(out)) {
3435 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3436 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003437 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303438 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003439 if (ret != 0) {
3440 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3441 __func__, ret);
3442 goto error_open;
3443 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003444 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3445 if (config->sample_rate == 0)
3446 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3447 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3448 config->sample_rate != 8000) {
3449 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3450 ret = -EINVAL;
3451 goto error_open;
3452 }
3453 out->sample_rate = config->sample_rate;
3454 out->config.rate = config->sample_rate;
3455 if (config->format == AUDIO_FORMAT_DEFAULT)
3456 config->format = AUDIO_FORMAT_PCM_16_BIT;
3457 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3458 config->format = AUDIO_FORMAT_PCM_16_BIT;
3459 ret = -EINVAL;
3460 goto error_open;
3461 }
3462 out->format = config->format;
3463 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3464 out->config = pcm_config_afe_proxy_playback;
3465 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003466 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3467 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3468 out->config = pcm_config_low_latency;
3469 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003470 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003471 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3473 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003474 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003475 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3476 format = AUDIO_FORMAT_PCM_16_BIT;
3477 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3478 out->config = pcm_config_deep_buffer;
3479 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003480 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003481 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003482 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003483 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003484 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003485 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486 }
3487
Mingming Yin21854652016-04-13 11:54:02 -07003488 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d out->flags:%x, flags:%x",
3489 __func__, devices, flags, format, out->sample_rate, out->bit_width, out->flags, flags);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003490 /* TODO remove this hardcoding and check why width is zero*/
3491 if (out->bit_width == 0)
3492 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003493 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3494 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003495 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303496 out->bit_width, out->channel_mask,
3497 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003498 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3499 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3500 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003501 if(adev->primary_output == NULL)
3502 adev->primary_output = out;
3503 else {
3504 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003505 ret = -EEXIST;
3506 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003507 }
3508 }
3509
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510 /* Check if this usecase is already existing */
3511 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003512 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3513 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003516 ret = -EEXIST;
3517 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518 }
3519 pthread_mutex_unlock(&adev->lock);
3520
3521 out->stream.common.get_sample_rate = out_get_sample_rate;
3522 out->stream.common.set_sample_rate = out_set_sample_rate;
3523 out->stream.common.get_buffer_size = out_get_buffer_size;
3524 out->stream.common.get_channels = out_get_channels;
3525 out->stream.common.get_format = out_get_format;
3526 out->stream.common.set_format = out_set_format;
3527 out->stream.common.standby = out_standby;
3528 out->stream.common.dump = out_dump;
3529 out->stream.common.set_parameters = out_set_parameters;
3530 out->stream.common.get_parameters = out_get_parameters;
3531 out->stream.common.add_audio_effect = out_add_audio_effect;
3532 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3533 out->stream.get_latency = out_get_latency;
3534 out->stream.set_volume = out_set_volume;
3535 out->stream.write = out_write;
3536 out->stream.get_render_position = out_get_render_position;
3537 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003538 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003541 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003542 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003543
3544 config->format = out->stream.common.get_format(&out->stream.common);
3545 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3546 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3547
3548 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303549 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003550 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003551
3552 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3553 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3554 popcount(out->channel_mask), out->playback_started);
3555
Eric Laurent994a6932013-07-17 11:51:42 -07003556 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003558
3559error_open:
3560 free(out);
3561 *stream_out = NULL;
3562 ALOGD("%s: exit: ret %d", __func__, ret);
3563 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564}
3565
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003566static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567 struct audio_stream_out *stream)
3568{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003569 struct stream_out *out = (struct stream_out *)stream;
3570 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003571 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003572
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303573 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3574
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003575 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303576 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003577 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303578 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003579 if(ret != 0)
3580 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3581 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003582 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003583 out_standby(&stream->common);
3584
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003585 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003586 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003587 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003588 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003589 if (out->compr_config.codec != NULL)
3590 free(out->compr_config.codec);
3591 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003592
3593 if (adev->voice_tx_output == out)
3594 adev->voice_tx_output = NULL;
3595
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003596 pthread_cond_destroy(&out->cond);
3597 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003598 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003599 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600}
3601
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003602static void close_compress_sessions(struct audio_device *adev)
3603{
Mingming Yin7b762e72015-03-04 13:47:32 -08003604 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303605 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003606 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003607 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303608
3609 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003610 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303611 if (is_offload_usecase(usecase->id)) {
3612 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003613 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3614 out = usecase->stream.out;
3615 pthread_mutex_unlock(&adev->lock);
3616 out_standby(&out->stream.common);
3617 pthread_mutex_lock(&adev->lock);
3618 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303619 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003620 }
3621 pthread_mutex_unlock(&adev->lock);
3622}
3623
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3625{
3626 struct audio_device *adev = (struct audio_device *)dev;
3627 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003629 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003630 int ret;
3631 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003633 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303636 if (!parms)
3637 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003638 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3639 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303640 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303641 if (strstr(snd_card_status, "OFFLINE")) {
3642 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303643 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003644 //close compress sessions on OFFLINE status
3645 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303646 } else if (strstr(snd_card_status, "ONLINE")) {
3647 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303648 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003649 //send dts hpx license if enabled
3650 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303651 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303652 }
3653
3654 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003655 status = voice_set_parameters(adev, parms);
3656 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003657 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003659 status = platform_set_parameters(adev->platform, parms);
3660 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003661 goto done;
3662
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003663 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3664 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003665 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003666 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3667 adev->bluetooth_nrec = true;
3668 else
3669 adev->bluetooth_nrec = false;
3670 }
3671
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003672 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3673 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3675 adev->screen_off = false;
3676 else
3677 adev->screen_off = true;
3678 }
3679
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003680 ret = str_parms_get_int(parms, "rotation", &val);
3681 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003682 bool reverse_speakers = false;
3683 switch(val) {
3684 // FIXME: note that the code below assumes that the speakers are in the correct placement
3685 // relative to the user when the device is rotated 90deg from its default rotation. This
3686 // assumption is device-specific, not platform-specific like this code.
3687 case 270:
3688 reverse_speakers = true;
3689 break;
3690 case 0:
3691 case 90:
3692 case 180:
3693 break;
3694 default:
3695 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003696 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003697 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003698 if (status == 0) {
3699 if (adev->speaker_lr_swap != reverse_speakers) {
3700 adev->speaker_lr_swap = reverse_speakers;
3701 // only update the selected device if there is active pcm playback
3702 struct audio_usecase *usecase;
3703 struct listnode *node;
3704 list_for_each(node, &adev->usecase_list) {
3705 usecase = node_to_item(node, struct audio_usecase, list);
3706 if (usecase->type == PCM_PLAYBACK) {
3707 select_devices(adev, usecase->id);
3708 break;
3709 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003710 }
3711 }
3712 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003713 }
3714
Mingming Yin514a8bc2014-07-29 15:22:21 -07003715 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3716 if (ret >= 0) {
3717 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3718 adev->bt_wb_speech_enabled = true;
3719 else
3720 adev->bt_wb_speech_enabled = false;
3721 }
3722
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003723 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3724 if (ret >= 0) {
3725 val = atoi(value);
3726 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3727 ALOGV("cache new edid");
3728 platform_cache_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003729 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3730 /*
3731 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
3732 * Per AudioPolicyManager, USB device is higher priority than WFD.
3733 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
3734 * If WFD use case occupies AFE proxy, it may result unintended behavior while
3735 * starting voice call on USB
3736 */
3737 ALOGV("detected USB connect .. disable proxy");
3738 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003739 }
3740 }
3741
3742 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3743 if (ret >= 0) {
3744 val = atoi(value);
3745 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3746 ALOGV("invalidate cached edid");
3747 platform_invalidate_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003748 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3749 ALOGV("detected USB disconnect .. enable proxy");
3750 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003751 }
3752 }
3753
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003754 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003755
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003756done:
3757 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003758 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303759error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003760 ALOGV("%s: exit with code(%d)", __func__, status);
3761 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003762}
3763
3764static char* adev_get_parameters(const struct audio_hw_device *dev,
3765 const char *keys)
3766{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003767 struct audio_device *adev = (struct audio_device *)dev;
3768 struct str_parms *reply = str_parms_create();
3769 struct str_parms *query = str_parms_create_str(keys);
3770 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303771 char value[256] = {0};
3772 int ret = 0;
3773
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003774 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003775 if (reply) {
3776 str_parms_destroy(reply);
3777 }
3778 if (query) {
3779 str_parms_destroy(query);
3780 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003781 ALOGE("adev_get_parameters: failed to create query or reply");
3782 return NULL;
3783 }
3784
Naresh Tannirud7205b62014-06-20 02:54:48 +05303785 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3786 sizeof(value));
3787 if (ret >=0) {
3788 int val = 1;
3789 pthread_mutex_lock(&adev->snd_card_status.lock);
3790 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3791 val = 0;
3792 pthread_mutex_unlock(&adev->snd_card_status.lock);
3793 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3794 goto exit;
3795 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003796
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003797 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003798 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003799 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003800 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303801 pthread_mutex_unlock(&adev->lock);
3802
Naresh Tannirud7205b62014-06-20 02:54:48 +05303803exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003804 str = str_parms_to_str(reply);
3805 str_parms_destroy(query);
3806 str_parms_destroy(reply);
3807
3808 ALOGV("%s: exit: returns - %s", __func__, str);
3809 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810}
3811
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003812static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003813{
3814 return 0;
3815}
3816
3817static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3818{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003819 int ret;
3820 struct audio_device *adev = (struct audio_device *)dev;
3821 pthread_mutex_lock(&adev->lock);
3822 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003823 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003824 pthread_mutex_unlock(&adev->lock);
3825 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003826}
3827
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003828static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3829 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003830{
3831 return -ENOSYS;
3832}
3833
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003834static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3835 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003836{
3837 return -ENOSYS;
3838}
3839
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003840static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3841 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003842{
3843 return -ENOSYS;
3844}
3845
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003846static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3847 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848{
3849 return -ENOSYS;
3850}
3851
3852static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3853{
3854 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003855
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003856 pthread_mutex_lock(&adev->lock);
3857 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003858 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003860 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003861 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003862 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003863 adev->current_call_output = NULL;
3864 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003865 }
3866 pthread_mutex_unlock(&adev->lock);
3867 return 0;
3868}
3869
3870static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3871{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003872 int ret;
3873
3874 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003875 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003876 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3877 pthread_mutex_unlock(&adev->lock);
3878
3879 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003880}
3881
3882static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3883{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003884 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003885 return 0;
3886}
3887
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003888static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889 const struct audio_config *config)
3890{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003891 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003892
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003893 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3894 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003895}
3896
3897static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003898 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899 audio_devices_t devices,
3900 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003901 struct audio_stream_in **stream_in,
3902 audio_input_flags_t flags __unused,
3903 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003904 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003905{
3906 struct audio_device *adev = (struct audio_device *)dev;
3907 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003908 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003909 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003910 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912 *stream_in = NULL;
3913 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3914 return -EINVAL;
3915
3916 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003917
3918 if (!in) {
3919 ALOGE("failed to allocate input stream");
3920 return -ENOMEM;
3921 }
3922
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303923 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003924 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3925 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003926
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003927 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003928 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930 in->stream.common.get_sample_rate = in_get_sample_rate;
3931 in->stream.common.set_sample_rate = in_set_sample_rate;
3932 in->stream.common.get_buffer_size = in_get_buffer_size;
3933 in->stream.common.get_channels = in_get_channels;
3934 in->stream.common.get_format = in_get_format;
3935 in->stream.common.set_format = in_set_format;
3936 in->stream.common.standby = in_standby;
3937 in->stream.common.dump = in_dump;
3938 in->stream.common.set_parameters = in_set_parameters;
3939 in->stream.common.get_parameters = in_get_parameters;
3940 in->stream.common.add_audio_effect = in_add_audio_effect;
3941 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3942 in->stream.set_gain = in_set_gain;
3943 in->stream.read = in_read;
3944 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3945
3946 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003947 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003948 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003949 in->standby = 1;
3950 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003951 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003952 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003953
3954 /* Update config params with the requested sample rate and channels */
3955 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003956 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3957 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3958 is_low_latency = true;
3959#if LOW_LATENCY_CAPTURE_USE_CASE
3960 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3961#endif
3962 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003963 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003965 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003966
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003967 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303968 if (adev->mode != AUDIO_MODE_IN_CALL) {
3969 ret = -EINVAL;
3970 goto err_open;
3971 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003972 if (config->sample_rate == 0)
3973 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3974 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3975 config->sample_rate != 8000) {
3976 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3977 ret = -EINVAL;
3978 goto err_open;
3979 }
3980 if (config->format == AUDIO_FORMAT_DEFAULT)
3981 config->format = AUDIO_FORMAT_PCM_16_BIT;
3982 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3983 config->format = AUDIO_FORMAT_PCM_16_BIT;
3984 ret = -EINVAL;
3985 goto err_open;
3986 }
3987
3988 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3989 in->config = pcm_config_afe_proxy_record;
3990 in->config.channels = channel_count;
3991 in->config.rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05303992 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
3993 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07003994 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003995 audio_extn_compr_cap_format_supported(config->format) &&
3996 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003997 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003998 } else {
3999 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004000 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004001 buffer_size = get_input_buffer_size(config->sample_rate,
4002 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004003 channel_count,
4004 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004005 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004006 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4007 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4008 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004009 (in->config.rate == 8000 || in->config.rate == 16000 ||
4010 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004011 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4012 voice_extn_compress_voip_open_input_stream(in);
4013 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004014 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004015
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004016 /* This stream could be for sound trigger lab,
4017 get sound trigger pcm if present */
4018 audio_extn_sound_trigger_check_and_get_session(in);
4019
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004020 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004021 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004022 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004023
4024err_open:
4025 free(in);
4026 *stream_in = NULL;
4027 return ret;
4028}
4029
4030static void adev_close_input_stream(struct audio_hw_device *dev,
4031 struct audio_stream_in *stream)
4032{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004033 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004034 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004035 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304036
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304037 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004038
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304039 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004040 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304041
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004042 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304043 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004044 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304045 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004046 if (ret != 0)
4047 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4048 __func__, ret);
4049 } else
4050 in_standby(&stream->common);
4051
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004052 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004053 audio_extn_ssr_deinit();
4054 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055
Mingming Yine62d7842013-10-25 16:26:03 -07004056 if(audio_extn_compr_cap_enabled() &&
4057 audio_extn_compr_cap_format_supported(in->config.format))
4058 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004059
Mingming Yinfd7607b2016-01-22 12:48:44 -08004060 if (in->is_st_session) {
4061 ALOGV("%s: sound trigger pcm stop lab", __func__);
4062 audio_extn_sound_trigger_stop_lab(in);
4063 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004064 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004065 return;
4066}
4067
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004068static int adev_dump(const audio_hw_device_t *device __unused,
4069 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004070{
4071 return 0;
4072}
4073
4074static int adev_close(hw_device_t *device)
4075{
4076 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004077
4078 if (!adev)
4079 return 0;
4080
4081 pthread_mutex_lock(&adev_init_lock);
4082
4083 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004084 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004085 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004086 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004087 audio_route_free(adev->audio_route);
4088 free(adev->snd_dev_ref_cnt);
4089 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004090 if (adev->adm_deinit)
4091 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004092 free(device);
4093 adev = NULL;
4094 }
4095 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004097 return 0;
4098}
4099
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004100/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4101 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4102 * just that it _might_ work.
4103 */
4104static int period_size_is_plausible_for_low_latency(int period_size)
4105{
4106 switch (period_size) {
4107 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004108 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004109 case 240:
4110 case 320:
4111 case 480:
4112 return 1;
4113 default:
4114 return 0;
4115 }
4116}
4117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004118static int adev_open(const hw_module_t *module, const char *name,
4119 hw_device_t **device)
4120{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004121 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004122 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4123
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004124 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004125 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004126 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004127 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004128 ALOGD("%s: returning existing instance of adev", __func__);
4129 ALOGD("%s: exit", __func__);
4130 pthread_mutex_unlock(&adev_init_lock);
4131 return 0;
4132 }
4133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004134 adev = calloc(1, sizeof(struct audio_device));
4135
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004136 if (!adev) {
4137 pthread_mutex_unlock(&adev_init_lock);
4138 return -ENOMEM;
4139 }
4140
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004141 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4142
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004143 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4144 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4145 adev->device.common.module = (struct hw_module_t *)module;
4146 adev->device.common.close = adev_close;
4147
4148 adev->device.init_check = adev_init_check;
4149 adev->device.set_voice_volume = adev_set_voice_volume;
4150 adev->device.set_master_volume = adev_set_master_volume;
4151 adev->device.get_master_volume = adev_get_master_volume;
4152 adev->device.set_master_mute = adev_set_master_mute;
4153 adev->device.get_master_mute = adev_get_master_mute;
4154 adev->device.set_mode = adev_set_mode;
4155 adev->device.set_mic_mute = adev_set_mic_mute;
4156 adev->device.get_mic_mute = adev_get_mic_mute;
4157 adev->device.set_parameters = adev_set_parameters;
4158 adev->device.get_parameters = adev_get_parameters;
4159 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4160 adev->device.open_output_stream = adev_open_output_stream;
4161 adev->device.close_output_stream = adev_close_output_stream;
4162 adev->device.open_input_stream = adev_open_input_stream;
4163 adev->device.close_input_stream = adev_close_input_stream;
4164 adev->device.dump = adev_dump;
4165
4166 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004168 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004169 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004170 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004171 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004172 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004173 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004174 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004175 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004176 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004177 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004178 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004179 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304180 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304181 adev->perf_lock_opts[0] = 0x101;
4182 adev->perf_lock_opts[1] = 0x20E;
4183 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304184
4185 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4186 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004187 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004188 adev->platform = platform_init(adev);
4189 if (!adev->platform) {
4190 free(adev->snd_dev_ref_cnt);
4191 free(adev);
4192 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4193 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004194 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004195 return -EINVAL;
4196 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004197
Naresh Tanniru4c630392014-05-12 01:05:52 +05304198 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4199
Eric Laurentc4aef752013-09-12 17:45:53 -07004200 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4201 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4202 if (adev->visualizer_lib == NULL) {
4203 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4204 } else {
4205 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4206 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004207 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004208 "visualizer_hal_start_output");
4209 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004210 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004211 "visualizer_hal_stop_output");
4212 }
4213 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004214 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004215 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004216
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004217 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4218 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4219 if (adev->offload_effects_lib == NULL) {
4220 ALOGE("%s: DLOPEN failed for %s", __func__,
4221 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4222 } else {
4223 ALOGV("%s: DLOPEN successful for %s", __func__,
4224 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4225 adev->offload_effects_start_output =
4226 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4227 "offload_effects_bundle_hal_start_output");
4228 adev->offload_effects_stop_output =
4229 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4230 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004231 adev->offload_effects_set_hpx_state =
4232 (int (*)(bool))dlsym(adev->offload_effects_lib,
4233 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304234 adev->offload_effects_get_parameters =
4235 (void (*)(struct str_parms *, struct str_parms *))
4236 dlsym(adev->offload_effects_lib,
4237 "offload_effects_bundle_get_parameters");
4238 adev->offload_effects_set_parameters =
4239 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4240 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004241 }
4242 }
4243
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004244 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4245 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4246 if (adev->adm_lib == NULL) {
4247 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4248 } else {
4249 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4250 adev->adm_init = (adm_init_t)
4251 dlsym(adev->adm_lib, "adm_init");
4252 adev->adm_deinit = (adm_deinit_t)
4253 dlsym(adev->adm_lib, "adm_deinit");
4254 adev->adm_register_input_stream = (adm_register_input_stream_t)
4255 dlsym(adev->adm_lib, "adm_register_input_stream");
4256 adev->adm_register_output_stream = (adm_register_output_stream_t)
4257 dlsym(adev->adm_lib, "adm_register_output_stream");
4258 adev->adm_deregister_stream = (adm_deregister_stream_t)
4259 dlsym(adev->adm_lib, "adm_deregister_stream");
4260 adev->adm_request_focus = (adm_request_focus_t)
4261 dlsym(adev->adm_lib, "adm_request_focus");
4262 adev->adm_abandon_focus = (adm_abandon_focus_t)
4263 dlsym(adev->adm_lib, "adm_abandon_focus");
4264 }
4265 }
4266
Mingming Yin514a8bc2014-07-29 15:22:21 -07004267 adev->bt_wb_speech_enabled = false;
4268
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004269 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004270 *device = &adev->device.common;
4271
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004272 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4273 &adev->streams_output_cfg_list);
4274
Kiran Kandi910e1862013-10-29 13:29:42 -07004275 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004276
4277 char value[PROPERTY_VALUE_MAX];
4278 int trial;
4279 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4280 trial = atoi(value);
4281 if (period_size_is_plausible_for_low_latency(trial)) {
4282 pcm_config_low_latency.period_size = trial;
4283 pcm_config_low_latency.start_threshold = trial / 4;
4284 pcm_config_low_latency.avail_min = trial / 4;
4285 configured_low_latency_capture_period_size = trial;
4286 }
4287 }
4288 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4289 trial = atoi(value);
4290 if (period_size_is_plausible_for_low_latency(trial)) {
4291 configured_low_latency_capture_period_size = trial;
4292 }
4293 }
4294
vivek mehta446c3962015-09-14 10:57:35 -07004295 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004296 pthread_mutex_unlock(&adev_init_lock);
4297
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004298 if (adev->adm_init)
4299 adev->adm_data = adev->adm_init();
4300
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304301 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004302 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004303 return 0;
4304}
4305
4306static struct hw_module_methods_t hal_module_methods = {
4307 .open = adev_open,
4308};
4309
4310struct audio_module HAL_MODULE_INFO_SYM = {
4311 .common = {
4312 .tag = HARDWARE_MODULE_TAG,
4313 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4314 .hal_api_version = HARDWARE_HAL_API_VERSION,
4315 .id = AUDIO_HARDWARE_MODULE_ID,
4316 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004317 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318 .methods = &hal_module_methods,
4319 },
4320};